// This is a generated file, modify: generate/templates/class_content.cc.
#include <nan.h>
#include <string.h>

extern "C" {
#include <git2.h>
}


#include "../include/functions/copy.h"
#include "../include/macros.h"
#include "../include/repository.h"

#include "../include/config.h"
#include "../include/repository.h"
#include "../include/signature.h"
#include "../include/reference.h"
#include "../include/index.h"
#include "../include/repository_init_options.h"
#include "../include/odb.h"
#include "../include/refdb.h"
#include "../include/oid.h"

#include <iostream>

using namespace std;
using namespace v8;
using namespace node;

GitRepository::GitRepository(git_repository *raw, bool selfFreeing)
{
  this->raw = raw;
  this->selfFreeing = selfFreeing;
}

GitRepository::~GitRepository()
{
  if (this->selfFreeing) {
    git_repository_free(this->raw);
  }
}

void GitRepository::InitializeComponent(Handle<v8::Object> target)
{
  NanScope();

  Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(JSNewFunction);

  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  tpl->SetClassName(NanNew<String>("Repository"));

  NODE_SET_PROTOTYPE_METHOD(tpl, "config", Config);
  NODE_SET_PROTOTYPE_METHOD(tpl, "configSnapshot", ConfigSnapshot);
  NODE_SET_PROTOTYPE_METHOD(tpl, "detachHead", DetachHead);
  NODE_SET_PROTOTYPE_METHOD(tpl, "getNamespace", GetNamespace);
  NODE_SET_PROTOTYPE_METHOD(tpl, "head", Head);
  NODE_SET_PROTOTYPE_METHOD(tpl, "headDetached", HeadDetached);
  NODE_SET_PROTOTYPE_METHOD(tpl, "headUnborn", HeadUnborn);
  NODE_SET_PROTOTYPE_METHOD(tpl, "index", Index);
  NODE_SET_METHOD(tpl, "init", Init);
  NODE_SET_METHOD(tpl, "initExt", InitExt);
  NODE_SET_METHOD(tpl, "initInitOptions", InitInitOptions);
  NODE_SET_PROTOTYPE_METHOD(tpl, "isBare", IsBare);
  NODE_SET_PROTOTYPE_METHOD(tpl, "isEmpty", IsEmpty);
  NODE_SET_PROTOTYPE_METHOD(tpl, "isShallow", IsShallow);
  NODE_SET_PROTOTYPE_METHOD(tpl, "messageRemove", MessageRemove);
  NODE_SET_PROTOTYPE_METHOD(tpl, "odb", Odb);
  NODE_SET_METHOD(tpl, "open", Open);
  NODE_SET_METHOD(tpl, "openBare", OpenBare);
  NODE_SET_METHOD(tpl, "openExt", OpenExt);
  NODE_SET_PROTOTYPE_METHOD(tpl, "path", Path);
  NODE_SET_PROTOTYPE_METHOD(tpl, "refdb", Refdb);
  NODE_SET_PROTOTYPE_METHOD(tpl, "setHead", SetHead);
  NODE_SET_PROTOTYPE_METHOD(tpl, "setHeadDetached", SetHeadDetached);
  NODE_SET_PROTOTYPE_METHOD(tpl, "setNamespace", SetNamespace);
  NODE_SET_PROTOTYPE_METHOD(tpl, "setWorkdir", SetWorkdir);
  NODE_SET_PROTOTYPE_METHOD(tpl, "state", State);
  NODE_SET_PROTOTYPE_METHOD(tpl, "stateCleanup", StateCleanup);
  NODE_SET_PROTOTYPE_METHOD(tpl, "workdir", Workdir);
  NODE_SET_METHOD(tpl, "wrapOdb", WrapOdb);

  Local<Function> _constructor_template = tpl->GetFunction();
  NanAssignPersistent(constructor_template, _constructor_template);
  target->Set(NanNew<String>("Repository"), _constructor_template);
}

NAN_METHOD(GitRepository::JSNewFunction)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsExternal()) {
    return NanThrowError("A new GitRepository cannot be instantiated.");
  }

  GitRepository* object = new GitRepository(static_cast<git_repository *>(Handle<External>::Cast(args[0])->Value()), args[1]->BooleanValue());
  object->Wrap(args.This());

  NanReturnValue(args.This());
}

Handle<Value> GitRepository::New(void *raw, bool selfFreeing)
{
  NanEscapableScope();
  Handle<Value> argv[2] = { NanNew<External>((void *)raw), NanNew<Boolean>(selfFreeing) };
  return NanEscapeScope(NanNew<Function>(GitRepository::constructor_template)->NewInstance(2, argv));
}

git_repository *GitRepository::GetValue()
{
  return this->raw;
}

git_repository **GitRepository::GetRefValue()
{
  return &this->raw;
}


/*
     * @param Config callback
   */
NAN_METHOD(GitRepository::Config)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  ConfigBaton* baton = new ConfigBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

  baton->repo = ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue();

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[0]));
  ConfigWorker *worker = new ConfigWorker(baton, callback);
  worker->SaveToPersistent("repo", args.This());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::ConfigWorker::Execute()
{
  int result = git_repository_config(
                 &baton->out,baton->repo    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::ConfigWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitConfig baton->out
      to = GitConfig::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }


  delete baton;
}

/*
     * @param Config callback
   */
NAN_METHOD(GitRepository::ConfigSnapshot)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  ConfigSnapshotBaton* baton = new ConfigSnapshotBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

  baton->repo = ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue();

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[0]));
  ConfigSnapshotWorker *worker = new ConfigSnapshotWorker(baton, callback);
  worker->SaveToPersistent("repo", args.This());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::ConfigSnapshotWorker::Execute()
{
  int result = git_repository_config_snapshot(
                 &baton->out,baton->repo    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::ConfigSnapshotWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitConfig baton->out
      to = GitConfig::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }


  delete baton;
}

/*
   * @param Signature signature
   * @param String reflog_message
     * @return Number  result    */
NAN_METHOD(GitRepository::DetachHead)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Signature signature is required.");
  }

  if (args.Length() == 1 || !args[1]->IsString()) {
    return NanThrowError("String reflog_message is required.");
  }

// start convert_from_v8 block
  const git_signature * from_signature;
  from_signature = ObjectWrap::Unwrap<GitSignature>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_reflog_message;

  String::Utf8Value reflog_message(args[1]->ToString());
  from_reflog_message = (const char *) strdup(*reflog_message);
// end convert_from_v8 block
  int result = git_repository_detach_head(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
                 ,from_signature
                 ,from_reflog_message
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @return String  result    */
NAN_METHOD(GitRepository::GetNamespace)
{
  NanEscapableScope();

  const char * result = git_repository_get_namespace(
                          ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
                        );
  // null checks on pointers
  if (!result) {
    NodeGitPsueodoNanReturnEscapingValue(NanUndefined());
  }

  Handle<Value> to;
// start convert_to_v8 block
  if (result) {
    to = NanNew<String>(result);
  } else {
    to = NanNull();
  }

  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @param Reference callback
   */
NAN_METHOD(GitRepository::Head)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  HeadBaton* baton = new HeadBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

  baton->repo = ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue();

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[0]));
  HeadWorker *worker = new HeadWorker(baton, callback);
  worker->SaveToPersistent("repo", args.This());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::HeadWorker::Execute()
{
  int result = git_repository_head(
                 &baton->out,baton->repo    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::HeadWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRefs baton->out
      to = GitRefs::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }


  delete baton;
}

/*
     * @return Number  result    */
NAN_METHOD(GitRepository::HeadDetached)
{
  NanEscapableScope();

  int result = git_repository_head_detached(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @return Number  result    */
NAN_METHOD(GitRepository::HeadUnborn)
{
  NanEscapableScope();

  int result = git_repository_head_unborn(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @param Index callback
   */
NAN_METHOD(GitRepository::Index)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  IndexBaton* baton = new IndexBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

  baton->repo = ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue();

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[0]));
  IndexWorker *worker = new IndexWorker(baton, callback);
  worker->SaveToPersistent("repo", args.This());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::IndexWorker::Execute()
{
  int result = git_repository_index(
                 &baton->out,baton->repo    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::IndexWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitIndex baton->out
      to = GitIndex::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }


  delete baton;
}

/*
  * @param String path
   * @param Number is_bare
    * @param Repository callback
   */
NAN_METHOD(GitRepository::Init)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsString()) {
    return NanThrowError("String path is required.");
  }

  if (args.Length() == 1 || !args[1]->IsNumber()) {
    return NanThrowError("Number is_bare is required.");
  }

  if (args.Length() == 2 || !args[2]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  InitBaton* baton = new InitBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  const char * from_path;

  String::Utf8Value path(args[0]->ToString());
  from_path = (const char *) strdup(*path);
// end convert_from_v8 block
  baton->path = from_path;
// start convert_from_v8 block
  unsigned int from_is_bare;
  from_is_bare = (unsigned int)   args[1]->ToNumber()->Value();
// end convert_from_v8 block
  baton->is_bare = from_is_bare;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[2]));
  InitWorker *worker = new InitWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("path", args[0]->ToObject());
  if (!args[1]->IsUndefined() && !args[1]->IsNull())
    worker->SaveToPersistent("is_bare", args[1]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::InitWorker::Execute()
{
  int result = git_repository_init(
                 &baton->out,baton->path,baton->is_bare    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::InitWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRepository baton->out
      to = GitRepository::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }

  free((void *)baton->path);

  delete baton;
}

/*
  * @param String repo_path
   * @param RepositoryInitOptions opts
    * @param Repository callback
   */
NAN_METHOD(GitRepository::InitExt)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsString()) {
    return NanThrowError("String repo_path is required.");
  }

  if (args.Length() == 1 || !args[1]->IsObject()) {
    return NanThrowError("RepositoryInitOptions opts is required.");
  }

  if (args.Length() == 2 || !args[2]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  InitExtBaton* baton = new InitExtBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  const char * from_repo_path;

  String::Utf8Value repo_path(args[0]->ToString());
  from_repo_path = (const char *) strdup(*repo_path);
// end convert_from_v8 block
  baton->repo_path = from_repo_path;
// start convert_from_v8 block
  git_repository_init_options * from_opts;
  from_opts = ObjectWrap::Unwrap<GitRepositoryInitOptions>(args[1]->ToObject())->GetValue();
// end convert_from_v8 block
  baton->opts = from_opts;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[2]));
  InitExtWorker *worker = new InitExtWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("repo_path", args[0]->ToObject());
  if (!args[1]->IsUndefined() && !args[1]->IsNull())
    worker->SaveToPersistent("opts", args[1]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::InitExtWorker::Execute()
{
  int result = git_repository_init_ext(
                 &baton->out,baton->repo_path,baton->opts    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::InitExtWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRepository baton->out
      to = GitRepository::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }

  free((void *)baton->repo_path);

  delete baton;
}

/*
 * @param RepositoryInitOptions opts
   * @param Number version
     * @return Number  result    */
NAN_METHOD(GitRepository::InitInitOptions)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("RepositoryInitOptions opts is required.");
  }

  if (args.Length() == 1 || !args[1]->IsNumber()) {
    return NanThrowError("Number version is required.");
  }

// start convert_from_v8 block
  git_repository_init_options * from_opts;
  from_opts = ObjectWrap::Unwrap<GitRepositoryInitOptions>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  unsigned int from_version;
  from_version = (unsigned int)   args[1]->ToNumber()->Value();
// end convert_from_v8 block
  int result = git_repository_init_init_options(
                 from_opts
                 ,from_version
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @return Number  result    */
NAN_METHOD(GitRepository::IsBare)
{
  NanEscapableScope();

  int result = git_repository_is_bare(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @return Number  result    */
NAN_METHOD(GitRepository::IsEmpty)
{
  NanEscapableScope();

  int result = git_repository_is_empty(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @return Number  result    */
NAN_METHOD(GitRepository::IsShallow)
{
  NanEscapableScope();

  int result = git_repository_is_shallow(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @return Number  result    */
NAN_METHOD(GitRepository::MessageRemove)
{
  NanEscapableScope();

  int result = git_repository_message_remove(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @param Odb callback
   */
NAN_METHOD(GitRepository::Odb)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  OdbBaton* baton = new OdbBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

  baton->repo = ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue();

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[0]));
  OdbWorker *worker = new OdbWorker(baton, callback);
  worker->SaveToPersistent("repo", args.This());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::OdbWorker::Execute()
{
  int result = git_repository_odb(
                 &baton->out,baton->repo    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::OdbWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitOdb baton->out
      to = GitOdb::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }


  delete baton;
}

/*
  * @param String path
    * @param Repository callback
   */
NAN_METHOD(GitRepository::Open)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsString()) {
    return NanThrowError("String path is required.");
  }

  if (args.Length() == 1 || !args[1]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  OpenBaton* baton = new OpenBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  const char * from_path;

  String::Utf8Value path(args[0]->ToString());
  from_path = (const char *) strdup(*path);
// end convert_from_v8 block
  baton->path = from_path;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[1]));
  OpenWorker *worker = new OpenWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("path", args[0]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::OpenWorker::Execute()
{
  int result = git_repository_open(
                 &baton->out,baton->path    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::OpenWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRepository baton->out
      to = GitRepository::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }

  free((void *)baton->path);

  delete baton;
}

/*
  * @param String bare_path
    * @param Repository callback
   */
NAN_METHOD(GitRepository::OpenBare)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsString()) {
    return NanThrowError("String bare_path is required.");
  }

  if (args.Length() == 1 || !args[1]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  OpenBareBaton* baton = new OpenBareBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  const char * from_bare_path;

  String::Utf8Value bare_path(args[0]->ToString());
  from_bare_path = (const char *) strdup(*bare_path);
// end convert_from_v8 block
  baton->bare_path = from_bare_path;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[1]));
  OpenBareWorker *worker = new OpenBareWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("bare_path", args[0]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::OpenBareWorker::Execute()
{
  int result = git_repository_open_bare(
                 &baton->out,baton->bare_path    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::OpenBareWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRepository baton->out
      to = GitRepository::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }

  free((void *)baton->bare_path);

  delete baton;
}

/*
  * @param String path
   * @param Number flags
   * @param String ceiling_dirs
    * @param Repository callback
   */
NAN_METHOD(GitRepository::OpenExt)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsString()) {
    return NanThrowError("String path is required.");
  }

  if (args.Length() == 1 || !args[1]->IsNumber()) {
    return NanThrowError("Number flags is required.");
  }

  if (args.Length() == 2 || !args[2]->IsString()) {
    return NanThrowError("String ceiling_dirs is required.");
  }

  if (args.Length() == 3 || !args[3]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  OpenExtBaton* baton = new OpenExtBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  const char * from_path;

  String::Utf8Value path(args[0]->ToString());
  from_path = (const char *) strdup(*path);
// end convert_from_v8 block
  baton->path = from_path;
// start convert_from_v8 block
  unsigned int from_flags;
  from_flags = (unsigned int)   args[1]->ToNumber()->Value();
// end convert_from_v8 block
  baton->flags = from_flags;
// start convert_from_v8 block
  const char * from_ceiling_dirs;

  String::Utf8Value ceiling_dirs(args[2]->ToString());
  from_ceiling_dirs = (const char *) strdup(*ceiling_dirs);
// end convert_from_v8 block
  baton->ceiling_dirs = from_ceiling_dirs;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[3]));
  OpenExtWorker *worker = new OpenExtWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("path", args[0]->ToObject());
  if (!args[1]->IsUndefined() && !args[1]->IsNull())
    worker->SaveToPersistent("flags", args[1]->ToObject());
  if (!args[2]->IsUndefined() && !args[2]->IsNull())
    worker->SaveToPersistent("ceiling_dirs", args[2]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::OpenExtWorker::Execute()
{
  int result = git_repository_open_ext(
                 &baton->out,baton->path,baton->flags,baton->ceiling_dirs    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::OpenExtWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRepository baton->out
      to = GitRepository::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }

  free((void *)baton->path);
  free((void *)baton->ceiling_dirs);

  delete baton;
}

/*
     * @return String  result    */
NAN_METHOD(GitRepository::Path)
{
  NanEscapableScope();

  const char * result = git_repository_path(
                          ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
                        );
  // null checks on pointers
  if (!result) {
    NodeGitPsueodoNanReturnEscapingValue(NanUndefined());
  }

  Handle<Value> to;
// start convert_to_v8 block
  if (result) {
    to = NanNew<String>(result);
  } else {
    to = NanNull();
  }

  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @param Refdb callback
   */
NAN_METHOD(GitRepository::Refdb)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  RefdbBaton* baton = new RefdbBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

  baton->repo = ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue();

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[0]));
  RefdbWorker *worker = new RefdbWorker(baton, callback);
  worker->SaveToPersistent("repo", args.This());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::RefdbWorker::Execute()
{
  int result = git_repository_refdb(
                 &baton->out,baton->repo    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::RefdbWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRefdb baton->out
      to = GitRefdb::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }


  delete baton;
}

/*
   * @param String refname
   * @param Signature signature
   * @param String log_message
     * @return Number  result    */
NAN_METHOD(GitRepository::SetHead)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsString()) {
    return NanThrowError("String refname is required.");
  }

  if (args.Length() == 1 || !args[1]->IsObject()) {
    return NanThrowError("Signature signature is required.");
  }

  if (args.Length() == 2 || !args[2]->IsString()) {
    return NanThrowError("String log_message is required.");
  }

// start convert_from_v8 block
  const char * from_refname;

  String::Utf8Value refname(args[0]->ToString());
  from_refname = (const char *) strdup(*refname);
// end convert_from_v8 block
// start convert_from_v8 block
  const git_signature * from_signature;
  from_signature = ObjectWrap::Unwrap<GitSignature>(args[1]->ToObject())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_log_message;

  String::Utf8Value log_message(args[2]->ToString());
  from_log_message = (const char *) strdup(*log_message);
// end convert_from_v8 block
  int result = git_repository_set_head(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
                 ,from_refname
                 ,from_signature
                 ,from_log_message
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
   * @param Oid commitish
   * @param Signature signature
   * @param String log_message
     * @return Number  result    */
NAN_METHOD(GitRepository::SetHeadDetached)
{
  NanEscapableScope();

  if (args.Length() == 0
      || (!args[0]->IsObject() && !args[0]->IsString())) {
    return NanThrowError("Oid commitish is required.");
  }

  if (args.Length() == 1 || !args[1]->IsObject()) {
    return NanThrowError("Signature signature is required.");
  }

  if (args.Length() == 2 || !args[2]->IsString()) {
    return NanThrowError("String log_message is required.");
  }

// start convert_from_v8 block
  const git_oid * from_commitish;
  if (args[0]->IsString()) {
    // Try and parse in a string to a git_oid
    String::Utf8Value oidString(args[0]->ToString());
    git_oid *oidOut = (git_oid *)malloc(sizeof(git_oid));

    if (git_oid_fromstr(oidOut, (const char *) strdup(*oidString)) != GIT_OK) {
      free(oidOut);

      if (giterr_last()) {
        return NanThrowError(giterr_last()->message);
      } else {
        return NanThrowError("Unknown Error");
      }
    }

    from_commitish = oidOut;
  } else {
    from_commitish = ObjectWrap::Unwrap<GitOid>(args[0]->ToObject())->GetValue();
  }
// end convert_from_v8 block
// start convert_from_v8 block
  const git_signature * from_signature;
  from_signature = ObjectWrap::Unwrap<GitSignature>(args[1]->ToObject())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_log_message;

  String::Utf8Value log_message(args[2]->ToString());
  from_log_message = (const char *) strdup(*log_message);
// end convert_from_v8 block
  int result = git_repository_set_head_detached(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
                 ,from_commitish
                 ,from_signature
                 ,from_log_message
               );
  if (args[0]->IsString()) {
    free(&from_commitish);
  }

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
   * @param String nmspace
     * @return Number  result    */
NAN_METHOD(GitRepository::SetNamespace)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsString()) {
    return NanThrowError("String nmspace is required.");
  }

// start convert_from_v8 block
  const char * from_nmspace;

  String::Utf8Value nmspace(args[0]->ToString());
  from_nmspace = (const char *) strdup(*nmspace);
// end convert_from_v8 block
  int result = git_repository_set_namespace(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
                 ,from_nmspace
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
   * @param String workdir
   * @param Number update_gitlink
     * @return Number  result    */
NAN_METHOD(GitRepository::SetWorkdir)
{
  NanEscapableScope();

  if (args.Length() == 0 || !args[0]->IsString()) {
    return NanThrowError("String workdir is required.");
  }

  if (args.Length() == 1 || !args[1]->IsNumber()) {
    return NanThrowError("Number update_gitlink is required.");
  }

// start convert_from_v8 block
  const char * from_workdir;

  String::Utf8Value workdir(args[0]->ToString());
  from_workdir = (const char *) strdup(*workdir);
// end convert_from_v8 block
// start convert_from_v8 block
  int from_update_gitlink;
  from_update_gitlink = (int)   args[1]->ToNumber()->Value();
// end convert_from_v8 block
  int result = git_repository_set_workdir(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
                 ,from_workdir
                 ,from_update_gitlink
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @return Number  result    */
NAN_METHOD(GitRepository::State)
{
  NanEscapableScope();

  int result = git_repository_state(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @return Number  result    */
NAN_METHOD(GitRepository::StateCleanup)
{
  NanEscapableScope();

  int result = git_repository_state_cleanup(
                 ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
               );

  Handle<Value> to;
// start convert_to_v8 block
  to = NanNew<Number>(result);
  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
     * @return String  result    */
NAN_METHOD(GitRepository::Workdir)
{
  NanEscapableScope();

  const char * result = git_repository_workdir(
                          ObjectWrap::Unwrap<GitRepository>(args.This())->GetValue()
                        );
  // null checks on pointers
  if (!result) {
    NodeGitPsueodoNanReturnEscapingValue(NanUndefined());
  }

  Handle<Value> to;
// start convert_to_v8 block
  if (result) {
    to = NanNew<String>(result);
  } else {
    to = NanNull();
  }

  // end convert_to_v8 block
  NodeGitPsueodoNanReturnEscapingValue(to);
}

/*
  * @param Odb odb
    * @param Repository callback
   */
NAN_METHOD(GitRepository::WrapOdb)
{
  NanScope();

  if (args.Length() == 0 || !args[0]->IsObject()) {
    return NanThrowError("Odb odb is required.");
  }

  if (args.Length() == 1 || !args[1]->IsFunction()) {
    return NanThrowError("Callback is required and must be a Function.");
  }

  WrapOdbBaton* baton = new WrapOdbBaton;

  baton->error_code = GIT_OK;
  baton->error = NULL;

// start convert_from_v8 block
  git_odb * from_odb;
  from_odb = ObjectWrap::Unwrap<GitOdb>(args[0]->ToObject())->GetValue();
// end convert_from_v8 block
  baton->odb = from_odb;

  NanCallback *callback = new NanCallback(Local<Function>::Cast(args[1]));
  WrapOdbWorker *worker = new WrapOdbWorker(baton, callback);
  if (!args[0]->IsUndefined() && !args[0]->IsNull())
    worker->SaveToPersistent("odb", args[0]->ToObject());

  NanAsyncQueueWorker(worker);
  NanReturnUndefined();
}

void GitRepository::WrapOdbWorker::Execute()
{
  int result = git_repository_wrap_odb(
                 &baton->out,baton->odb    );

  baton->error_code = result;

  if (result != GIT_OK && giterr_last() != NULL) {
    baton->error = git_error_dup(giterr_last());
  }

}

void GitRepository::WrapOdbWorker::HandleOKCallback()
{
  TryCatch try_catch;

  if (baton->error_code == GIT_OK) {
    Handle<Value> to;
// start convert_to_v8 block

    if (baton->out != NULL) {
      // GitRepository baton->out
      to = GitRepository::New((void *)baton->out, false);
    } else {
      to = NanNull();
    }

// end convert_to_v8 block
    Handle<Value> result = to;
    Handle<Value> argv[2] = {
      NanNull(),
      result
    };
    callback->Call(2, argv);
  } else {
    if (baton->error) {
      Handle<Value> argv[1] = {
        NanError(baton->error->message)
      };
      callback->Call(1, argv);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else {
      callback->Call(0, NULL);
    }

  }

  if (try_catch.HasCaught()) {
    node::FatalException(try_catch);
  }


  delete baton;
}
Persistent<Function> GitRepository::constructor_template;
