Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Oh jesus it's messy. So very messy. Oh god.

  • Loading branch information...
commit e3eb5c2cb836eec540f6a5a8f58e1bfd477548ca 1 parent 423a767
@samcday samcday authored
View
14 src/commit.cc
@@ -24,8 +24,7 @@
#include "commit.h"
#include "repository.h"
-#include "object_factory.h"
-#include "tree.h"
+//#include "tree.h"
#include <time.h>
#include <stdlib.h>
#include "signature.h"
@@ -91,10 +90,9 @@ Handle<Value> Commit::New(const Arguments& args) {
HandleScope scope;
REQ_ARGS(1);
- REQ_EXT_ARG(0, theCommit);
+ REQ_EXT_ARG(0, commitArg);
- Commit *commit = new Commit();
- commit->commit_ = (git_commit*)theCommit->Value();
+ Commit *commit = static_cast<Commit*>(commitArg->Value());
commit->Wrap(args.This());
return args.This();
@@ -330,11 +328,12 @@ int Commit::EIO_AfterSave(eio_req *req) {
return 0;
}
-void* Commit::loadInitData() {
+void* Commit::loadInitData(int *result) {
commit_data *data = new commit_data;
repository_->lockRepository();
const git_oid *commitId = git_commit_id(commit_);
git_oid_fmt(data->id, commitId);
+
data->message = new std::string(git_commit_message(commit_));
data->author = git_signature_dup(git_commit_author(commit_));
data->committer = git_signature_dup(git_commit_committer(commit_));
@@ -402,7 +401,8 @@ void Commit::setOwner(void *owner) {
repository_ = static_cast<Repository*>(owner);
}
-Commit::Commit() : GitObjectWrap() {
+Commit::Commit(git_commit *commit) : GitObjectWrap<Commit>() {
+ commit_ = commit;
}
Commit::~Commit() {
View
8 src/commit.h
@@ -8,11 +8,11 @@ namespace gitteh {
class Repository;
-class Commit : public GitObjectWrap {
+class Commit : public GitObjectWrap<Commit> {
public:
static Persistent<FunctionTemplate> constructor_template;
static void Init(Handle<Object>);
- Commit();
+ Commit(git_commit*);
~Commit();
static Handle<Value> SaveObject(Handle<Object>, Repository*, Handle<Value>, bool);
@@ -30,8 +30,8 @@ class Commit : public GitObjectWrap {
static Handle<Value> GetParent(const Arguments&);
static Handle<Value> Save(const Arguments&);
- void processInitData(void *data);
- void* loadInitData();
+ void processInitData(void*);
+ void* loadInitData(int*);
int parentCount_;
View
68 src/gitobjectwrap.h
@@ -6,23 +6,15 @@
namespace gitteh {
+template<class T>
class GitObjectWrap : public ObjectWrap {
public:
GitObjectWrap() : ObjectWrap() {
CREATE_MUTEX(gatekeeperLock_);
initialized_ = 0;
- initInterest_ = 0;
data_ = NULL;
}
- // Shortcut, if this is a newly allocated object for a newly created Git
- // object, then there's not going to be any threads fighting for access,
- // we just mark it as initialized straight up, no need to even use a mutex.
- void forceInitialized() {
- processInitData(NULL);
- initialized_ = true;
- }
-
bool isInitialized() {
LOCK_MUTEX(gatekeeperLock_);
bool initialized = initialized_;
@@ -31,27 +23,10 @@ class GitObjectWrap : public ObjectWrap {
return initialized;
}
- void registerInitInterest() {
- LOCK_MUTEX(gatekeeperLock_);
- Ref();
- UNLOCK_MUTEX(gatekeeperLock_);
- }
-
- void removeInitInterest() {
- LOCK_MUTEX(gatekeeperLock_);
- Unref();
- initInterest_--;
-
- if(initInterest_ == 0) {
- DESTROY_MUTEX(initLock_);
- }
- UNLOCK_MUTEX(gatekeeperLock_);
- }
-
- void waitForInitialization() {
+ int waitForInitialization() {
bool needInitialization = false;
LOCK_MUTEX(gatekeeperLock_);
- if(!initInterest_++) {
+ if(!initialized_) {
needInitialization = true;
CREATE_MUTEX(initLock_);
LOCK_MUTEX(initLock_);
@@ -59,9 +34,18 @@ class GitObjectWrap : public ObjectWrap {
UNLOCK_MUTEX(gatekeeperLock_);
if(needInitialization) {
- void* data = loadInitData();
- initializationDone(data);
- return;
+ int result = GIT_SUCCESS;
+ void* data = loadInitData(&result);
+
+ LOCK_MUTEX(gatekeeperLock_);
+ data_ = data;
+ UNLOCK_MUTEX(gatekeeperLock_);
+
+ UNLOCK_MUTEX(initLock_);
+
+ if(result != GIT_SUCCESS) {
+ return result;
+ }
}
//LOCK_MUTEX(initLock_);
@@ -75,21 +59,13 @@ class GitObjectWrap : public ObjectWrap {
usleep(1000);
}
UNLOCK_MUTEX(initLock_);
- }
- void syncInitialize(void *data) {
- LOCK_MUTEX(gatekeeperLock_);
- UNLOCK_MUTEX(gatekeeperLock_);
+ return GIT_SUCCESS;
}
- // Signalled by the thread that is building the commit data that the data
- // is now done and JS object can be finalized.
- void initializationDone(void *data) {
+ void syncInitialize(void *data) {
LOCK_MUTEX(gatekeeperLock_);
- data_ = data;
UNLOCK_MUTEX(gatekeeperLock_);
-
- UNLOCK_MUTEX(initLock_);
}
// This should only be called from main thread. When one or more requests
@@ -99,10 +75,11 @@ class GitObjectWrap : public ObjectWrap {
// the JS object. All the requests will call this, but only the first one
// will actually make anything meaningful happen.
void ensureInitDone() {
- // FIXME? don't think any locking is necessary here as this is ONLY
- // called from main thread.
LOCK_MUTEX(gatekeeperLock_);
- if(data_ != NULL) {
+ if(!initialized_) {
+ Handle<Value> constructorArgs[1] = { External::New(this) };
+ T::constructor_template->GetFunction()->NewInstance(1, constructorArgs);
+
processInitData(data_);
initialized_ = true;
data_ = NULL;
@@ -116,11 +93,10 @@ class GitObjectWrap : public ObjectWrap {
// This is implemented by actual object classes. Implements MUST free all
// resources allocated by the data on the heap.
virtual void processInitData(void *data) = 0;
- virtual void* loadInitData() = 0;
+ virtual void* loadInitData(int *result) = 0;
private:
bool initialized_;
- int initInterest_;
gitteh_lock gatekeeperLock_;
gitteh_lock initLock_;
void *data_;
View
14 src/gitteh.cc
@@ -25,24 +25,22 @@
#include "gitteh.h"
#include "commit.h"
-#include "tree.h"
#include "repository.h"
+/*#include "tree.h"
#include "index.h"
#include "index_entry.h"
#include "tag.h"
#include "rev_walker.h"
-#include "error.h"
#include "ref.h"
-#include "blob.h"
+#include "blob.h"*/
+#include "error.h"
#include "thread.h"
namespace gitteh {
-#if 0
static void gcNotif(GCType type, GCCallbackFlags flags) {
std::cout << "gc is happening yo.\n";
}
-#endif
extern "C" void
init(Handle<Object> target) {
@@ -50,17 +48,17 @@ init(Handle<Object> target) {
Repository::Init(target);
Commit::Init(target);
- Tree::Init(target);
+ /*Tree::Init(target);
Index::Init(target);
IndexEntry::Init(target);
Tag::Init(target);
RevWalker::Init(target);
Reference::Init(target);
- Blob::Init(target);
+ Blob::Init(target);*/
ErrorInit(target);
- //V8::AddGCPrologueCallback(gcNotif);
+ V8::AddGCPrologueCallback(gcNotif);
}
} // namespace gitteh
View
190 src/object_cache.h
@@ -0,0 +1,190 @@
+#ifndef GITTEH_OBJECT_CACHE_H
+#define GITTEH_OBJECT_CACHE_H
+
+#include "gitteh.h"
+#include <map>
+
+namespace gitteh {
+
+template <class P, class T, class S>
+class CachedGitObject;
+
+template<class P, class T, class S>
+class WrappedGitObjectCache {
+public:
+ inline Handle<Value> syncCacheObject(S* obj) {
+ HandleScope scope;
+ T* wrappedObj = wrapObject(obj);
+
+ if(!wrappedObj->isInitialized()) {
+ int result = wrappedObj->waitForInitialization();
+
+ std::cout << "res:"<<result<<"\n";
+ if(result != GIT_SUCCESS) {
+ THROW_GIT_ERROR("Couldn't get object.", result);
+ }
+
+ wrapWrappedObject(obj);
+ }
+
+ return scope.Close(Local<Object>::New(wrappedObj->handle_));
+ }
+
+ inline int asyncCacheObject(S* obj, T **wrappedObjRet) {
+ T* wrappedObj = wrapObject(obj);
+
+ int error = GIT_SUCCESS;
+ if(!wrappedObj->isInitialized()) {
+ error = wrappedObj->waitForInitialization();
+ if(error == GIT_SUCCESS) {
+ *wrappedObjRet = wrappedObj;
+ }
+ }
+
+ return error;
+ }
+
+ void asyncEnsureWrapped(S *wrappedObj) {
+ wrapWrappedObject(wrappedObj);
+ }
+
+ inline WrappedGitObjectCache(P *owner) {
+ CREATE_MUTEX(objectsLock);
+ owner_ = owner;
+ }
+
+ inline ~WrappedGitObjectCache() {
+ LOCK_MUTEX(objectsLock);
+
+ typename std::map<size_t, CachedGitObject<P, T,S>* >::const_iterator it = objects.begin();
+ typename std::map<size_t, CachedGitObject<P, T,S>* >::const_iterator end = objects.end();
+ CachedGitObject<P, T,S>* cachedObject;
+
+ while(it != end) {
+ cachedObject = it->second;
+
+ if(cachedObject->wrapped) {
+ cachedObject->handle.Dispose();
+ cachedObject->handle.Clear();
+ }
+
+ delete cachedObject;
+ ++it;
+ }
+
+ UNLOCK_MUTEX(objectsLock);
+ }
+
+protected:
+ // Returns the wrapping object for a git object. If there isn't one yet,
+ // it'll create it.
+ inline T* wrapObject(S* gitObj) {
+ CachedGitObject<P, T, S> *cachedObject;
+ bool newlyCreated = false;
+
+ LOCK_MUTEX(objectsLock);
+ cachedObject = objects[(size_t)gitObj];
+
+ if(cachedObject == NULL) {
+ std::cout << "CREATING.\n";
+ T* wrappedObject = new T(gitObj);
+ wrappedObject->setOwner(owner_);
+
+ newlyCreated = true;
+
+ cachedObject = new CachedGitObject<P, T, S>();
+ cachedObject->cache = this;
+ cachedObject->wrapped = false;
+ cachedObject->ref = gitObj;
+ cachedObject->object = wrappedObject;
+
+ objects[(size_t)gitObj] = cachedObject;
+ }
+
+ UNLOCK_MUTEX(objectsLock);
+
+ return cachedObject->object;
+ }
+
+ // Hurr.
+ inline void wrapWrappedObject(S* gitObj) {
+ LOCK_MUTEX(objectsLock);
+ CachedGitObject<P, T, S> *cachedObject = objects[(size_t)gitObj];
+ cachedObject->object->ensureInitDone();
+ cachedObject->handle = Persistent<Object>::New(cachedObject->object->handle_);
+ cachedObject->handle.MakeWeak(cachedObject, WeakCallback);
+ UNLOCK_MUTEX(objectsLock);
+ }
+
+/*
+ inline bool getObjectFor (S *ref, T **dest) {
+ HandleScope scope;
+
+ CachedGitObject<P, T, S> *cachedObject;
+ bool newlyCreated = false;
+
+ // Quick check for the managed object.
+ LOCK_MUTEX(objectsLock);
+ cachedObject = objects[(size_t)ref];
+
+ if(managedObject == NULL) {
+ // K we gotta go ahead and create.
+ Handle<Value> constructorArgs[1] = { External::New(ref) };
+ Handle<Object> jsObject = T::constructor_template->GetFunction()->NewInstance(1, constructorArgs);
+
+ managedObject = new ManagedObject<T, S>();
+ managedObject->store = this;
+ managedObject->object = ObjectWrap::Unwrap<T>(jsObject);
+ managedObject->ref = ref;
+
+
+
+ objects[(size_t)ref] = managedObject;
+
+ newlyCreated = true;
+ }
+
+ *dest = managedObject->object;
+ UNLOCK_MUTEX(objectsLock);
+
+ return newlyCreated;
+ }*/
+
+private:
+ static void WeakCallback (Persistent<Value> value, void *data) {
+ CachedGitObject<P, T, S> *cachedObject = (CachedGitObject<P, T, S>*)data;
+
+ assert(cachedObject->handle.IsNearDeath());
+
+ WrappedGitObjectCache<P, T, S> *cache = cachedObject->cache;
+
+ LOCK_MUTEX(cache->objectsLock);
+
+ typename std::map<size_t, CachedGitObject<P, T,S>* >::iterator it;
+ it = cache->objects.find((size_t)cachedObject->ref);
+ cache->objects.erase(it);
+
+ cachedObject->handle.Dispose();
+ cachedObject->handle.Clear();
+
+ UNLOCK_MUTEX(cache->objectsLock);
+ }
+
+ std::map<size_t, CachedGitObject<P, T, S>*> objects;
+ gitteh_lock objectsLock;
+ P *owner_;
+};
+
+template <class P, class T, class S>
+class CachedGitObject {
+public:
+ WrappedGitObjectCache<P, T, S> *cache;
+ T *object;
+ S *ref;
+ Persistent<Object> handle;
+ bool wrapped; // Is the object wrapped in a JS object yet?
+};
+
+} // namespace gitteh
+
+#endif // GITTEH_OBJECT_CACHE_H
View
2  src/object_factory.h
@@ -20,7 +20,6 @@ template<class P, class T, class S>
class ObjectFactory {
public:
ObjectFactory(P *owner) {
- owner_ = owner;
}
~ObjectFactory() {
@@ -136,7 +135,6 @@ class ObjectFactory {
CLEANUP_CALLBACK(callback);
}
- P *owner_;
ObjectStore<T,S> store_;
};
View
93 src/object_store.h
@@ -33,48 +33,10 @@ namespace gitteh {
// and only load all the relevant git object data into a struct if it hasn't
// been loaded into an object here already.
-template <class T, class S>
-class ManagedObject;
template <class T, class S>
class ObjectStore {
public:
- inline bool getObjectFor (S *ref, T **dest) {
- HandleScope scope;
-
- ManagedObject<T, S> *managedObject;
- bool newlyCreated = false;
-
- // Quick check for the managed object.
- LOCK_MUTEX(objectsLock);
- managedObject = objects[(size_t)ref];
- UNLOCK_MUTEX(objectsLock);
-
- if(managedObject == NULL) {
- // K we gotta go ahead and create.
- Handle<Value> constructorArgs[1] = { External::New(ref) };
- Handle<Object> jsObject = T::constructor_template->GetFunction()->NewInstance(1, constructorArgs);
-
- managedObject = new ManagedObject<T, S>();
- managedObject->store = this;
- managedObject->object = ObjectWrap::Unwrap<T>(jsObject);
- managedObject->ref = ref;
-
- managedObject->handle = Persistent<Object>::New(managedObject->object->handle_);
- managedObject->handle.MakeWeak(managedObject, WeakCallback);
-
- LOCK_MUTEX(objectsLock);
- objects[(size_t)ref] = managedObject;
- UNLOCK_MUTEX(objectsLock);
-
- newlyCreated = true;
- }
-
- //return scope.Close(managedObject->object->handle_);
- *dest = managedObject->object;
-
- return newlyCreated;
- }
inline void deleteObjectFor(S* ref) {
ManagedObject<T, S> *managedObject;
@@ -122,64 +84,11 @@ class ObjectStore {
return exists;
}
- inline ObjectStore() {
- CREATE_MUTEX(objectsLock);
- }
-
- inline ~ObjectStore() {
- // TODO: ooh, could be all sorts of fucked up deadlocks that locking the
- // mutex in a dtor might bring about. Gonna have to make sure this is ok
- // ... Later. Probably after another day of debugging stupid shit.
- LOCK_MUTEX(objectsLock);
-
- typename std::map<size_t, ManagedObject<T,S>* >::const_iterator it = objects.begin();
- typename std::map<size_t, ManagedObject<T,S>* >::const_iterator end = objects.end();
- ManagedObject<T,S>* managedObject;
-
- while(it != end) {
- managedObject = it->second;
- managedObject->handle.Dispose();
- managedObject->handle.Clear();
- delete managedObject;
- ++it;
- }
-
- UNLOCK_MUTEX(objectsLock);
- }
-
private:
- static void WeakCallback (Persistent<Value> value, void *data) {
- ManagedObject<T, S> *managedObject = (ManagedObject<T, S>*)data;
-
- assert(managedObject->handle.IsNearDeath());
- ObjectStore<T, S> *store = managedObject->store;
-
-
- LOCK_MUTEX(store->objectsLock);
-
- typename std::map<size_t, ManagedObject<T,S>* >::iterator it;
- it = store->objects.find((size_t)managedObject->ref);
- store->objects.erase(it);
-
- managedObject->handle.Dispose();
- managedObject->handle.Clear();
-
- UNLOCK_MUTEX(store->objectsLock);
- }
-
- std::map<size_t, ManagedObject<T, S>*> objects;
- gitteh_lock objectsLock;
};
-template <class T, class S>
-class ManagedObject {
-public:
- ObjectStore<T, S> *store;
- T *object;
- S *ref;
- Persistent<Object> handle;
-};
+
} // namespace gitteh
View
208 src/repository.cc
@@ -23,14 +23,14 @@
*/
#include "repository.h"
-#include "commit.h"
+#include "commit.h"/*
#include "tree.h"
#include "index.h"
#include "tag.h"
#include "rev_walker.h"
#include "ref.h"
#include "blob.h"
-#include "object_factory.h"
+#include "object_factory.h"*/
// DANGER, WILL ROBINSON!
// The nastiest code that will ever rape your eyeballs follows.
@@ -77,7 +77,7 @@
}
-#define FN_ASYNC_GET_OID_OBJECT(TYPE, GIT_TYPE) \
+#define FN_ASYNC_GET_OID_OBJECT(TYPE, GIT_TYPE, CACHE) \
int Repository::EIO_Get##TYPE(eio_req *req) { \
GET_REQUEST_DATA(object_request); \
GIT_TYPE *object; \
@@ -85,6 +85,13 @@
&object); \
if(reqData->error == GIT_SUCCESS) { \
reqData->object = object; \
+ TYPE *wrappedObject = NULL; \
+ reqData->error = reqData->repo->CACHE->asyncCacheObject( \
+ object, &wrappedObject); \
+ std::cout << reqData->error << "\n"; \
+ if(reqData->error == GIT_SUCCESS) { \
+ reqData->wrappedObject = wrappedObject; \
+ } \
} \
return 0; \
}
@@ -119,17 +126,20 @@
} \
else { \
if(reqData->create) { \
- TYPE *obj = reqData->repo->FACTORY->newObject( \
+ /*TYPE *obj = reqData->repo->FACTORY->newObject( \
static_cast<GIT_TYPE*>(reqData->object)); \
callbackArgs[0] = Null(); \
callbackArgs[1] = obj->handle_; \
TRIGGER_CALLBACK(); \
- reqData->callback.Dispose(); \
+ reqData->callback.Dispose();*/ \
} \
else { \
- reqData->repo->FACTORY->asyncRequestObject( \
- static_cast<GIT_TYPE*>(reqData->object), \
- reqData->callback); \
+ TYPE *wrappedObject = static_cast<TYPE*>(reqData->wrappedObject); \
+ reqData->repo->FACTORY->asyncEnsureWrapped(wrappedObject); \
+ callbackArgs[0] = Undefined(); \
+ callbackArgs[1] = Local<Object>::New(wrappedObject->handle_); \
+ TRIGGER_CALLBACK(); \
+ reqData->callback.Dispose(); \
} \
} \
delete reqData; \
@@ -190,14 +200,14 @@
request->create = true; \
REQUEST_DETACH(repo, EIO_Create##TYPE, EIO_Return##TYPE);
-#define SYNC_GET_OID_OBJECT(TYPE, GIT_TYPE, FACTORY) \
+#define SYNC_GET_OID_OBJECT(TYPE, GIT_TYPE, CACHE) \
GIT_TYPE *object; \
int res = repo->get##TYPE(&oidArg, &object); \
if(res != GIT_SUCCESS) { \
THROW_GIT_ERROR("Git error.", res); \
} \
- return scope.Close(repo->FACTORY-> \
- syncRequestObject(object)->handle_);
+ return scope.Close(repo->CACHE-> \
+ syncCacheObject(object));
#define SYNC_GET_NAMED_OBJECT(TYPE, GIT_TYPE, FACTORY) \
GIT_TYPE *object; \
@@ -232,6 +242,7 @@ struct object_request {
std::string *name;
std::string *target;
void *object;
+ void *wrappedObject;
bool create;
};
@@ -296,7 +307,7 @@ void Repository::Init(Handle<Object> target) {
constructor_template->SetClassName(String::New("Repository"));
t->InstanceTemplate()->SetInternalFieldCount(1);
- NODE_SET_PROTOTYPE_METHOD(t, "getCommit", GetCommit);
+ NODE_SET_PROTOTYPE_METHOD(t, "getCommit", GetCommit);/*
NODE_SET_PROTOTYPE_METHOD(t, "getTree", GetTree);
NODE_SET_PROTOTYPE_METHOD(t, "getTag", GetTag);
NODE_SET_PROTOTYPE_METHOD(t, "getReference", GetReference);
@@ -312,13 +323,52 @@ void Repository::Init(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(t, "listReferences", ListReferences);
NODE_SET_PROTOTYPE_METHOD(t, "exists", Exists);
- NODE_SET_PROTOTYPE_METHOD(t, "getIndex", GetIndex);
+ NODE_SET_PROTOTYPE_METHOD(t, "getIndex", GetIndex);*/
NODE_SET_METHOD(target, "openRepository", OpenRepository);
NODE_SET_METHOD(target, "openRepository2", OpenRepository2);
NODE_SET_METHOD(target, "initRepository", InitRepository);
}
+Handle<Value> Repository::New(const Arguments& args) {
+ HandleScope scope;
+
+ REQ_ARGS(2);
+ REQ_EXT_ARG(0, repoArg);
+ REQ_STR_ARG(1, pathArg);
+
+ Repository *repo = new Repository();
+ repo->Wrap(args.This());
+
+ repo->repo_ = static_cast<git_repository*>(repoArg->Value());
+ repo->path_ = *pathArg;
+ repo->odb_ = git_repository_database(repo->repo_);
+
+ args.This()->Set(String::New("path"), String::New(repo->path_), (PropertyAttribute)(ReadOnly | DontDelete));
+
+ // HUGE FUCKING TODO:
+ // IN MOTHER FUCKING CAPITALS.
+ // FOR SOME FUCKING REASON THE REPOSITORY IS GETTING GARBAGE COLLECTED MID
+ // RUN WHEN I DO STRESS TESTS LIKE TRAVERSING COMMIT HISTORY 1000 TIMES
+ // SIMULTANEOUSLY. THIS IS FUCKING STUPID BECAUSE THE FUCKING REPO OBJECT
+ // STILL HAS A FUCKING REF IN THE FUCKING USERLAND SCRIPT, BUT CUNTS WILL BE
+ // FUCKING CUNTS RIGHT? SO ANYWAY I FOUND THIS OUT AFTER LIKE 8 HOURS OF
+ // DEBUGGING BULLSHIT FUCKING RANDOM SEGFAULTS ALL OVER THE PLACE. YEAH.
+ // AWESOME. I GOT LUCKY IN ONE OF THE SEGFAULTS AND SAW IN GDB THAT THE CUNT
+ // WAS ALL FUCKED UP. ANYWAY, I DISCOVERED THAT IF I ATTACHED THE REPO TO
+ // THE GLOBAL PROCESS OBJECT THEN REPO WOULDN'T GET REAPO'D AND AS SUCH MY
+ // HARD WORK WOULDN'T COME UNDONE LIKE A HOOKER'S BRA CLASP. THERE MUST BE
+ // SOME SORT OF WEIRD V8 OPTIMIZATION THAT LOOKS AT LOCAL VARIABLES IN A
+ // SCRIPT AND SENSES IF THE CUNTS AREN'T BEING REFERENCED ANYMORE, THEN IT
+ // MUST CONSIDER THE LOCAL JS VARIABLE "WEAK" OR SOME SHIT. ANYWAY, IT'S
+ // FUCKED AND I DON'T LIKE IT. FOR NOW I'M ADDING REF() HERE TO MAKE SURE
+ // THAT A REPO OBJECT CAN NEVER BE MOTHERFUCKING GARBAGE COLLECTED. WHEN I
+ // KNOW MORE ABOUT NOT BEING A SHITHEAD AT CODING SHIT THEN I'LL REVISIT
+ // THIS SUCKER.
+ repo->Ref();
+ return args.This();
+}
+
Handle<Value> Repository::OpenRepository(const Arguments& args) {
HandleScope scope;
REQ_ARGS(1);
@@ -346,8 +396,11 @@ Handle<Value> Repository::OpenRepository(const Arguments& args) {
args[0]
};
- return scope.Close(Repository::constructor_template->GetFunction()
- ->NewInstance(2, constructorArgs));
+
+ Local<Object> repoObj = Repository::constructor_template->GetFunction()
+ ->NewInstance(2, constructorArgs);
+
+ return scope.Close(Local<Object>::New(repoObj));
}
}
@@ -608,45 +661,7 @@ int Repository::EIO_AfterInitRepository(eio_req *req) {
return 0;
}
-Handle<Value> Repository::New(const Arguments& args) {
- HandleScope scope;
-
- REQ_ARGS(2);
- REQ_EXT_ARG(0, repoArg);
- REQ_STR_ARG(1, pathArg);
-
- Repository *repo = new Repository();
- repo->Wrap(args.This());
-
- repo->repo_ = static_cast<git_repository*>(repoArg->Value());
- repo->path_ = *pathArg;
- repo->odb_ = git_repository_database(repo->repo_);
-
- args.This()->Set(String::New("path"), String::New(repo->path_), (PropertyAttribute)(ReadOnly | DontDelete));
-
- // HUGE FUCKING TODO:
- // IN MOTHER FUCKING CAPITALS.
- // FOR SOME FUCKING REASON THE REPOSITORY IS GETTING GARBAGE COLLECTED MID
- // RUN WHEN I DO STRESS TESTS LIKE TRAVERSING COMMIT HISTORY 1000 TIMES
- // SIMULTANEOUSLY. THIS IS FUCKING STUPID BECAUSE THE FUCKING REPO OBJECT
- // STILL HAS A FUCKING REF IN THE FUCKING USERLAND SCRIPT, BUT CUNTS WILL BE
- // FUCKING CUNTS RIGHT? SO ANYWAY I FOUND THIS OUT AFTER LIKE 8 HOURS OF
- // DEBUGGING BULLSHIT FUCKING RANDOM SEGFAULTS ALL OVER THE PLACE. YEAH.
- // AWESOME. I GOT LUCKY IN ONE OF THE SEGFAULTS AND SAW IN GDB THAT THE CUNT
- // WAS ALL FUCKED UP. ANYWAY, I DISCOVERED THAT IF I ATTACHED THE REPO TO
- // THE GLOBAL PROCESS OBJECT THEN REPO WOULDN'T GET REAPO'D AND AS SUCH MY
- // HARD WORK WOULDN'T COME UNDONE LIKE A HOOKER'S BRA CLASP. THERE MUST BE
- // SOME SORT OF WEIRD V8 OPTIMIZATION THAT LOOKS AT LOCAL VARIABLES IN A
- // SCRIPT AND SENSES IF THE CUNTS AREN'T BEING REFERENCED ANYMORE, THEN IT
- // MUST CONSIDER THE LOCAL JS VARIABLE "WEAK" OR SOME SHIT. ANYWAY, IT'S
- // FUCKED AND I DON'T LIKE IT. FOR NOW I'M ADDING REF() HERE TO MAKE SURE
- // THAT A REPO OBJECT CAN NEVER BE MOTHERFUCKING GARBAGE COLLECTED. WHEN I
- // KNOW MORE ABOUT NOT BEING A SHITHEAD AT CODING SHIT THEN I'LL REVISIT
- // THIS SUCKER.
- repo->Ref();
- return args.This();
-}
-
+#if 0
Handle<Value> Repository::CreateCommit(const Arguments& args) {
HandleScope scope;
Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());
@@ -678,7 +693,7 @@ Handle<Value> Repository::CreateBlob(const Arguments& args) {
return scope.Close(Blob::SaveObject(blobObjArg, repo, callback, true));
}
-
+#endif
Handle<Value> Repository::GetCommit(const Arguments& args) {
HandleScope scope;
Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());
@@ -690,10 +705,12 @@ Handle<Value> Repository::GetCommit(const Arguments& args) {
ASYNC_PREPARE_GET_OID_OBJECT(Commit, git_commit);
}
else {
- SYNC_GET_OID_OBJECT(Commit, git_commit, commitFactory_);
+ SYNC_GET_OID_OBJECT(Commit, git_commit, commitCache_);
}
}
+#if 0
+
Handle<Value> Repository::CreateTree(const Arguments& args) {
HandleScope scope;
Repository *repo = ObjectWrap::Unwrap<Repository>(args.This());
@@ -1220,10 +1237,63 @@ int Repository::EIO_AfterExists(eio_req *req) {
// ==========
// COMMIT EIO
// ==========
-FN_ASYNC_GET_OID_OBJECT(Commit, git_commit)
-FN_ASYNC_CREATE_OBJECT(Commit, git_commit)
-FN_ASYNC_RETURN_OBJECT_VIA_FACTORY(Commit, git_commit, commitFactory_)
+FN_ASYNC_GET_OID_OBJECT(Commit, git_commit, commitCache_)
+//FN_ASYNC_CREATE_OBJECT(Commit, git_commit)
+FN_ASYNC_RETURN_OBJECT_VIA_FACTORY(Commit, git_commit, commitCache_)
+#endif
+
+int Repository::EIO_GetCommit(eio_req *req) {
+ object_request *reqData = static_cast<object_request*>(req->data);
+
+ git_commit *commit;
+ int result = reqData->repo->getCommit(&reqData->oid, &commit);
+
+ reqData->wrappedObject = NULL;
+ if(result == GIT_SUCCESS) {
+ reqData->object = commit;
+
+ Commit *commitObject;
+ reqData->error = reqData->repo->commitCache_->asyncCacheObject(
+ commit, &commitObject);
+
+ if(reqData->error == GIT_SUCCESS) {
+ reqData->wrappedObject = commitObject;
+ }
+ }
+
+ return 0;
+}
+
+int Repository::EIO_ReturnCommit(eio_req *req) {
+ HandleScope scope;
+ object_request *reqData = static_cast<object_request*>(req->data);
+
+ ev_unref(EV_DEFAULT_UC);
+ reqData->repo->Unref();
+ Handle<Value> callbackArgs[2];
+ if(reqData->error != GIT_SUCCESS) {
+ Handle<Value> error = CreateGitError(String::New(
+ "Git error."), reqData->error);
+ callbackArgs[0] = error;
+ callbackArgs[1] = Null();
+ }
+ else {
+ callbackArgs[0] = Undefined();
+
+ Commit *wrappedCommit = static_cast<Commit*>(reqData->wrappedObject);
+ git_commit *commit = static_cast<git_commit*>(reqData->object);
+ reqData->repo->commitCache_->asyncEnsureWrapped(commit);
+ callbackArgs[1] = Local<Object>::New(wrappedCommit->handle_);
+ }
+
+ TRIGGER_CALLBACK();
+ reqData->callback.Dispose();
+ delete reqData;
+
+ return 0;
+}
+#if 0
// ========
// TREE EIO
// ========
@@ -1299,26 +1369,26 @@ int Repository::EIO_CreateOidRef(eio_req *req) {
// ===========
FN_ASYNC_CREATE_OBJECT(RevWalker, git_revwalk)
FN_ASYNC_RETURN_OBJECT_VIA_WRAP(RevWalker, git_revwalk)
-
+#endif
Repository::Repository() {
CREATE_MUTEX(gitLock_);
CREATE_MUTEX(refLock_);
- commitFactory_ = new ObjectFactory<Repository, Commit, git_commit>(this);
- referenceFactory_ = new ObjectFactory<Repository, Reference, git_reference>(this);
+ commitCache_ = new WrappedGitObjectCache<Repository, Commit, git_commit>(this);
+ /*referenceFactory_ = new ObjectFactory<Repository, Reference, git_reference>(this);
treeFactory_ = new ObjectFactory<Repository, Tree, git_tree>(this);
tagFactory_ = new ObjectFactory<Repository, Tag, git_tag>(this);
- blobFactory_ = new ObjectFactory<Repository, Blob, git_blob>(this);
+ blobFactory_ = new ObjectFactory<Repository, Blob, git_blob>(this);*/
- index_ = NULL;
+ //index_ = NULL;
}
Repository::~Repository() {
- delete commitFactory_;
- delete referenceFactory_;
+ delete commitCache_;
+ /*delete referenceFactory_;
delete treeFactory_;
delete tagFactory_;
- delete blobFactory_;
+ delete blobFactory_;*/
close();
}
@@ -1338,6 +1408,7 @@ int Repository::getCommit(git_oid *id, git_commit **commit) {
return result;
}
+#if 0
int Repository::createCommit(git_commit **commit) {
#ifdef FIXME
int result;
@@ -1463,9 +1534,12 @@ int Repository::createRawObject(git_rawobj** rawObj) {
}
#endif
+
+
void Repository::notifyIndexDead() {
index_ = NULL;
}
+#endif
void Repository::lockRepository() {
LOCK_MUTEX(gitLock_);
View
13 src/repository.h
@@ -2,7 +2,7 @@
#define GITTEH_REPO_H
#include "gitteh.h"
-#include "object_store.h"
+#include "object_cache.h"
namespace gitteh {
@@ -21,7 +21,7 @@ class Repository : public ObjectWrap {
public:
static Persistent<FunctionTemplate> constructor_template;
- template<class, class,class> friend class ObjectFactory;
+ template<class, class,class> friend class WrappedGitObjectCache;
Repository();
~Repository();
@@ -36,11 +36,11 @@ class Repository : public ObjectWrap {
void lockRefs();
void unlockRefs();
- ObjectFactory<Repository, Commit, git_commit> *commitFactory_;
- ObjectFactory<Repository, Tag, git_tag> *tagFactory_;
+ WrappedGitObjectCache<Repository, Commit, git_commit> *commitCache_;
+ /*ObjectFactory<Repository, Tag, git_tag> *tagFactory_;
ObjectFactory<Repository, Tree, git_tree> *treeFactory_;
ObjectFactory<Repository, Reference, git_reference> *referenceFactory_;
- ObjectFactory<Repository, Blob, git_blob> *blobFactory_;
+ ObjectFactory<Repository, Blob, git_blob> *blobFactory_;*/
void notifyIndexDead();
@@ -54,6 +54,7 @@ class Repository : public ObjectWrap {
static Handle<Value> InitRepository(const Arguments&);
static Handle<Value> New(const Arguments&);
+
static Handle<Value> GetODB(const Arguments&);
static Handle<Value> GetCommit(const Arguments&);
static Handle<Value> GetTree(const Arguments&);
@@ -145,7 +146,7 @@ class Repository : public ObjectWrap {
int DoRefPacking();
- Index *index_;
+ //Index *index_;
// For now, I'm using one lock for anything that calls a git_* api function.
// I could probably have different locks for different sections of libgit2,
View
17 test.js
@@ -0,0 +1,17 @@
+var gitteh = require("gitteh"),
+ path = require("path");
+
+var repo = gitteh.openRepository(path.join(__dirname, ".git"));
+
+for(var i = 0; i < 10; i++) {
+var commit = repo.getCommit("5108bce15012edcceb48f9ff25f519e5eb5c15ae", function(err, commit) {
+ console.log("commitargs", arguments);gc();
+});
+
+console.log("commit", repo.getCommit("5108bce15012edcceb48f9ff25f519e5eb5c15ae"));
+gc();
+}
+
+/*var commit = repo.getCommit("5108bce15012edcceb48f9ff25f519e5eb5c15ae", function(err, commit) {
+ console.log("commit", arguments);
+});*/
View
3  wscript
@@ -74,5 +74,6 @@ def build(ctx):
obj = ctx.new_task_gen('cxx', 'shlib', 'node_addon')
obj.target = 'gitteh'
- obj.source = 'src/gitteh.cc src/commit.cc src/tree.cc src/repository.cc src/index.cc src/index_entry.cc src/tag.cc src/rev_walker.cc src/ref.cc src/blob.cc'
+ obj.source = 'src/gitteh.cc src/commit.cc src/repository.cc '
+ #src/tree.cc src/index.cc src/index_entry.cc src/tag.cc src/rev_walker.cc src/ref.cc src/blob.cc'
obj.uselib = 'GIT2'
Please sign in to comment.
Something went wrong with that request. Please try again.