// This is a generated file, modify: generate/templates/templates/class_content.cc

#include <nan.h>
#include <string.h>

extern "C" {
  #include <git2.h>
 }

#include "../include/nodegit.h"
#include "../include/lock_master.h"
#include "../include/functions/copy.h"
#include "../include/remote.h"
#include "nodegit_wrapper.cc"

  #include "../include/str_array_converter.h"
  #include "../include/remote_head.h"
  #include "../include/repository.h"
  #include "../include/remote_callbacks.h"
  #include "../include/proxy_options.h"
  #include "../include/strarray.h"
  #include "../include/remote_create_options.h"
  #include "../include/buf.h"
  #include "../include/fetch_options.h"
  #include "../include/refspec.h"
  #include "../include/push_options.h"
  #include "../include/indexer_progress.h"
 
#include <iostream>

using namespace std;
using namespace v8;
using namespace node;

  GitRemote::~GitRemote() {
    // this will cause an error if you have a non-self-freeing object that also needs
    // to save values. Since the object that will eventually free the object has no
    // way of knowing to free these values.
                                                                                                                                                                                 }

  void GitRemote::InitializeComponent(v8::Local<v8::Object> target, nodegit::Context *nodegitContext) {
    Nan::HandleScope scope;

    v8::Local<v8::External> nodegitExternal = Nan::New<v8::External>(nodegitContext);
    v8::Local<FunctionTemplate> tpl = Nan::New<FunctionTemplate>(JSNewFunction, nodegitExternal);

    tpl->InstanceTemplate()->SetInternalFieldCount(1);
    tpl->SetClassName(Nan::New("Remote").ToLocalChecked());

           Nan::SetMethod(tpl, "addFetch", AddFetch, nodegitExternal);
             Nan::SetMethod(tpl, "addPush", AddPush, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "autotag", Autotag, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "connect", Connect, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "connected", Connected, nodegitExternal);
             Nan::SetMethod(tpl, "create", Create, nodegitExternal);
             Nan::SetMethod(tpl, "createAnonymous", CreateAnonymous, nodegitExternal);
             Nan::SetMethod(tpl, "createDetached", CreateDetached, nodegitExternal);
             Nan::SetMethod(tpl, "createWithFetchspec", CreateWithFetchspec, nodegitExternal);
             Nan::SetMethod(tpl, "createWithOpts", CreateWithOpts, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "defaultBranch", DefaultBranch, nodegitExternal);
             Nan::SetMethod(tpl, "delete", Delete, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "disconnect", Disconnect, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "download", Download, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "dup", Dup, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "fetch", Fetch, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "getFetchRefspecs", GetFetchRefspecs, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "getPushRefspecs", GetPushRefspecs, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "getRefspec", GetRefspec, nodegitExternal);
             Nan::SetMethod(tpl, "isValidName", IsValidName, nodegitExternal);
             Nan::SetMethod(tpl, "list", List, nodegitExternal);
             Nan::SetMethod(tpl, "lookup", Lookup, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "name", Name, nodegitExternal);
             Nan::SetMethod(tpl, "nameIsValid", NameIsValid, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "owner", Owner, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "prune", Prune, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "pruneRefs", PruneRefs, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "push", Push, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "pushurl", Pushurl, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "refspecCount", RefspecCount, nodegitExternal);
             Nan::SetMethod(tpl, "rename", Rename, nodegitExternal);
             Nan::SetMethod(tpl, "setAutotag", SetAutotag, nodegitExternal);
             Nan::SetMethod(tpl, "setPushurl", SetPushurl, nodegitExternal);
             Nan::SetMethod(tpl, "setUrl", SetUrl, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "stats", Stats, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "stop", Stop, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "updateTips", UpdateTips, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "upload", Upload, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "url", Url, nodegitExternal);
            Nan::SetPrototypeMethod(tpl, "referenceList", ReferenceList, nodegitExternal);
    
    InitializeTemplate(tpl);

    v8::Local<Function> constructor_template = Nan::GetFunction(tpl).ToLocalChecked();
    nodegitContext->SaveToPersistent("GitRemote::Template", constructor_template);
    Nan::Set(target, Nan::New("Remote").ToLocalChecked(), constructor_template);
  }

  
/*
 * @param Repository repo
   * @param String remote
   * @param String refspec
     * @return Number  result    */
NAN_METHOD(GitRemote::AddFetch) {
  Nan::EscapableHandleScope scope;

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String remote is required.");
  }

  if (info.Length() == 2 || !info[2]->IsString()) {
    return Nan::ThrowError("String refspec is required.");
  }

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_remote = NULL;

  Nan::Utf8String remote(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_remote = (const char *) malloc(remote.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_remote, *remote, remote.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_remote) + remote.length()), 0, 1);
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_refspec = NULL;

  Nan::Utf8String refspec(Nan::To<v8::String>(info[2]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_refspec = (const char *) malloc(refspec.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_refspec, *refspec, refspec.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_refspec) + refspec.length()), 0, 1);
// end convert_from_v8 block

  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              from_repo
            ,
              from_remote
            ,
              from_refspec
    );

 int result =     git_remote_add_fetch(
          from_repo
,          from_remote
,          from_refspec
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
 * @param Repository repo
   * @param String remote
   * @param String refspec
     * @return Number  result    */
NAN_METHOD(GitRemote::AddPush) {
  Nan::EscapableHandleScope scope;

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String remote is required.");
  }

  if (info.Length() == 2 || !info[2]->IsString()) {
    return Nan::ThrowError("String refspec is required.");
  }

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_remote = NULL;

  Nan::Utf8String remote(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_remote = (const char *) malloc(remote.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_remote, *remote, remote.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_remote) + remote.length()), 0, 1);
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_refspec = NULL;

  Nan::Utf8String refspec(Nan::To<v8::String>(info[2]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_refspec = (const char *) malloc(refspec.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_refspec, *refspec, refspec.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_refspec) + refspec.length()), 0, 1);
// end convert_from_v8 block

  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              from_repo
            ,
              from_remote
            ,
              from_refspec
    );

 int result =     git_remote_add_push(
          from_repo
,          from_remote
,          from_refspec
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
     * @return Number  result    */
NAN_METHOD(GitRemote::Autotag) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 git_remote_autotag_option_t result =     git_remote_autotag(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
  
/*
   * @param Number direction
   * @param RemoteCallbacks callbacks
   * @param ProxyOptions proxy_opts
   * @param Strarray custom_headers
     */
NAN_METHOD(GitRemote::Connect) {

  if (info.Length() == 0 || !info[0]->IsNumber()) {
    return Nan::ThrowError("Number direction is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  ConnectBaton* baton = new ConnectBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();
// start convert_from_v8 block
  git_direction from_direction;
      from_direction = (git_direction)  (int) info[0].As<v8::Number>()->Value();
// end convert_from_v8 block
          baton->direction = from_direction;
          if (info[1]->IsNull() || info[1]->IsUndefined()) {
            baton->callbacks = nullptr;
          } else
            {
            auto conversionResult = ConfigurableGitRemoteCallbacks::fromJavascript(nodegitContext, info[1]);
            if (!conversionResult.result) {
              return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked());
            }

            auto convertedObject = conversionResult.result;
            cleanupHandles["callbacks"] = convertedObject;
            baton->callbacks = convertedObject->GetValue();
          }
           if (info[2]->IsNull() || info[2]->IsUndefined()) {
            baton->proxy_opts = nullptr;
          } else
            {
            auto conversionResult = ConfigurableGitProxyOptions::fromJavascript(nodegitContext, info[2]);
            if (!conversionResult.result) {
              return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked());
            }

            auto convertedObject = conversionResult.result;
            cleanupHandles["proxy_opts"] = convertedObject;
            baton->proxy_opts = convertedObject->GetValue();
          }
 // start convert_from_v8 block
  const git_strarray * from_custom_headers = NULL;

  from_custom_headers = StrArrayConverter::Convert(info[3]);
// end convert_from_v8 block
          baton->custom_headers = from_custom_headers;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  ConnectWorker *worker = new ConnectWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());
           worker->Reference("direction", info[0]);
            worker->Reference("callbacks", info[1]);
            worker->Reference("proxy_opts", info[2]);
            worker->Reference("custom_headers", info[3]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::ConnectWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->remote
          ,baton->callbacks
          ,baton->proxy_opts
          ,baton->custom_headers
  );

  return lockMaster;
}

void GitRemote::ConnectWorker::Execute() {
  git_error_clear();

    int result = git_remote_connect(
baton->remote,baton->direction,baton->callbacks,baton->proxy_opts,baton->custom_headers  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::ConnectWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.connect").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }


  delete baton;
}

void GitRemote::ConnectWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> result = Nan::Undefined();
              {
               auto objWrap = Nan::ObjectWrap::Unwrap<GitRemote>(GetFromPersistent("remote").As<v8::Object>());
             objWrap->SaveCleanupHandle(cleanupHandles["callbacks"]);
          }
             {
               auto objWrap = Nan::ObjectWrap::Unwrap<GitRemote>(GetFromPersistent("remote").As<v8::Object>());
             objWrap->SaveCleanupHandle(cleanupHandles["proxy_opts"]);
          }
      
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method connect has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.connect").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method connect has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.connect").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }


  delete baton;
}

   
/*
     * @return Number  result    */
NAN_METHOD(GitRemote::Connected) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 int result =     git_remote_connected(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
  
/*
  * @param Repository repo
   * @param String name
   * @param String url
    * @param Remote callback
   */
NAN_METHOD(GitRemote::Create) {

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String name is required.");
  }

  if (info.Length() == 2 || !info[2]->IsString()) {
    return Nan::ThrowError("String url is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  CreateBaton* baton = new CreateBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
          baton->repo = from_repo;
// start convert_from_v8 block
  const char * from_name = NULL;

  Nan::Utf8String name(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_name = (const char *) malloc(name.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_name, *name, name.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_name) + name.length()), 0, 1);
// end convert_from_v8 block
          baton->name = from_name;
// start convert_from_v8 block
  const char * from_url = NULL;

  Nan::Utf8String url(Nan::To<v8::String>(info[2]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_url = (const char *) malloc(url.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_url, *url, url.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_url) + url.length()), 0, 1);
// end convert_from_v8 block
          baton->url = from_url;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  CreateWorker *worker = new CreateWorker(baton, callback, cleanupHandles);

             worker->Reference<GitRepository>("repo", info[0]);
             worker->Reference("name", info[1]);
            worker->Reference("url", info[2]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::CreateWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->repo
          ,baton->name
          ,baton->url
  );

  return lockMaster;
}

void GitRemote::CreateWorker::Execute() {
  git_error_clear();

    int result = git_remote_create(
&baton->out,baton->repo,baton->name,baton->url  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::CreateWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.create").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

      free(baton->out);

  delete baton;
}

void GitRemote::CreateWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (baton->out != NULL) {
      v8::Local<v8::Array> owners = Nan::New<Array>(0);
          Nan::Set(
          owners,
          Nan::New<v8::Number>(owners->Length()),
          Nan::To<v8::Object>(GitRepository::New(
            git_remote_owner(baton->out),
            true
          )).ToLocalChecked()
        );
         v8ConversionSlot = GitRemote::New(
        baton->out,
        true
          , owners
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
         
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method create has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.create").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method create has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.create").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

        free(baton->out);
  }


  delete baton;
}

  
/*
  * @param Repository repo
   * @param String url
    * @param Remote callback
   */
NAN_METHOD(GitRemote::CreateAnonymous) {

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String url is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  CreateAnonymousBaton* baton = new CreateAnonymousBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
          baton->repo = from_repo;
// start convert_from_v8 block
  const char * from_url = NULL;

  Nan::Utf8String url(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_url = (const char *) malloc(url.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_url, *url, url.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_url) + url.length()), 0, 1);
// end convert_from_v8 block
          baton->url = from_url;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  CreateAnonymousWorker *worker = new CreateAnonymousWorker(baton, callback, cleanupHandles);

             worker->Reference<GitRepository>("repo", info[0]);
             worker->Reference("url", info[1]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::CreateAnonymousWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->repo
          ,baton->url
  );

  return lockMaster;
}

void GitRemote::CreateAnonymousWorker::Execute() {
  git_error_clear();

    int result = git_remote_create_anonymous(
&baton->out,baton->repo,baton->url  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::CreateAnonymousWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createAnonymous").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

      free(baton->out);

  delete baton;
}

void GitRemote::CreateAnonymousWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (baton->out != NULL) {
      v8::Local<v8::Array> owners = Nan::New<Array>(0);
          Nan::Set(
          owners,
          Nan::New<v8::Number>(owners->Length()),
          Nan::To<v8::Object>(GitRepository::New(
            git_remote_owner(baton->out),
            true
          )).ToLocalChecked()
        );
         v8ConversionSlot = GitRemote::New(
        baton->out,
        true
          , owners
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
       
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method createAnonymous has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createAnonymous").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method createAnonymous has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createAnonymous").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

        free(baton->out);
  }


  delete baton;
}

  
/*
  * @param String url
    * @param Remote callback
   */
NAN_METHOD(GitRemote::CreateDetached) {

  if (info.Length() == 0 || !info[0]->IsString()) {
    return Nan::ThrowError("String url is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  CreateDetachedBaton* baton = new CreateDetachedBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

// start convert_from_v8 block
  const char * from_url = NULL;

  Nan::Utf8String url(Nan::To<v8::String>(info[0]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_url = (const char *) malloc(url.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_url, *url, url.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_url) + url.length()), 0, 1);
// end convert_from_v8 block
          baton->url = from_url;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  CreateDetachedWorker *worker = new CreateDetachedWorker(baton, callback, cleanupHandles);

           worker->Reference("url", info[0]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::CreateDetachedWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->url
  );

  return lockMaster;
}

void GitRemote::CreateDetachedWorker::Execute() {
  git_error_clear();

    int result = git_remote_create_detached(
&baton->out,baton->url  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::CreateDetachedWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createDetached").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

      free(baton->out);

  delete baton;
}

void GitRemote::CreateDetachedWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (baton->out != NULL) {
        v8ConversionSlot = GitRemote::New(
        baton->out,
        true
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
     
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method createDetached has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createDetached").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method createDetached has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createDetached").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

        free(baton->out);
  }


  delete baton;
}

  
/*
  * @param Repository repo
   * @param String name
   * @param String url
   * @param String fetch
    * @param Remote callback
   */
NAN_METHOD(GitRemote::CreateWithFetchspec) {

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String name is required.");
  }

  if (info.Length() == 2 || !info[2]->IsString()) {
    return Nan::ThrowError("String url is required.");
  }

  if (info.Length() == 3 || !info[3]->IsString()) {
    return Nan::ThrowError("String fetch is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  CreateWithFetchspecBaton* baton = new CreateWithFetchspecBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
          baton->repo = from_repo;
// start convert_from_v8 block
  const char * from_name = NULL;

  Nan::Utf8String name(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_name = (const char *) malloc(name.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_name, *name, name.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_name) + name.length()), 0, 1);
// end convert_from_v8 block
          baton->name = from_name;
// start convert_from_v8 block
  const char * from_url = NULL;

  Nan::Utf8String url(Nan::To<v8::String>(info[2]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_url = (const char *) malloc(url.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_url, *url, url.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_url) + url.length()), 0, 1);
// end convert_from_v8 block
          baton->url = from_url;
// start convert_from_v8 block
  const char * from_fetch = NULL;

  Nan::Utf8String fetch(Nan::To<v8::String>(info[3]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_fetch = (const char *) malloc(fetch.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_fetch, *fetch, fetch.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_fetch) + fetch.length()), 0, 1);
// end convert_from_v8 block
          baton->fetch = from_fetch;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  CreateWithFetchspecWorker *worker = new CreateWithFetchspecWorker(baton, callback, cleanupHandles);

             worker->Reference<GitRepository>("repo", info[0]);
             worker->Reference("name", info[1]);
            worker->Reference("url", info[2]);
            worker->Reference("fetch", info[3]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::CreateWithFetchspecWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->repo
          ,baton->name
          ,baton->url
          ,baton->fetch
  );

  return lockMaster;
}

void GitRemote::CreateWithFetchspecWorker::Execute() {
  git_error_clear();

    int result = git_remote_create_with_fetchspec(
&baton->out,baton->repo,baton->name,baton->url,baton->fetch  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::CreateWithFetchspecWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createWithFetchspec").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

      free(baton->out);

  delete baton;
}

void GitRemote::CreateWithFetchspecWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (baton->out != NULL) {
      v8::Local<v8::Array> owners = Nan::New<Array>(0);
          Nan::Set(
          owners,
          Nan::New<v8::Number>(owners->Length()),
          Nan::To<v8::Object>(GitRepository::New(
            git_remote_owner(baton->out),
            true
          )).ToLocalChecked()
        );
         v8ConversionSlot = GitRemote::New(
        baton->out,
        true
          , owners
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
           
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method createWithFetchspec has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createWithFetchspec").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method createWithFetchspec has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createWithFetchspec").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

        free(baton->out);
  }


  delete baton;
}

  
/*
  * @param String url
   * @param RemoteCreateOptions opts
    * @param Remote callback
   */
NAN_METHOD(GitRemote::CreateWithOpts) {

  if (info.Length() == 0 || !info[0]->IsString()) {
    return Nan::ThrowError("String url is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  CreateWithOptsBaton* baton = new CreateWithOptsBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

// start convert_from_v8 block
  const char * from_url = NULL;

  Nan::Utf8String url(Nan::To<v8::String>(info[0]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_url = (const char *) malloc(url.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_url, *url, url.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_url) + url.length()), 0, 1);
// end convert_from_v8 block
          baton->url = from_url;
          if (info[1]->IsNull() || info[1]->IsUndefined()) {
            baton->opts = nullptr;
          } else
            {
            auto conversionResult = ConfigurableGitRemoteCreateOptions::fromJavascript(nodegitContext, info[1]);
            if (!conversionResult.result) {
              return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked());
            }

            auto convertedObject = conversionResult.result;
            cleanupHandles["opts"] = convertedObject;
            baton->opts = convertedObject->GetValue();
          }
 
  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  CreateWithOptsWorker *worker = new CreateWithOptsWorker(baton, callback, cleanupHandles);

           worker->Reference("url", info[0]);
            worker->Reference("opts", info[1]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::CreateWithOptsWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->url
          ,baton->opts
  );

  return lockMaster;
}

void GitRemote::CreateWithOptsWorker::Execute() {
  git_error_clear();

    int result = git_remote_create_with_opts(
&baton->out,baton->url,baton->opts  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::CreateWithOptsWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createWithOpts").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

      free(baton->out);

  delete baton;
}

void GitRemote::CreateWithOptsWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (baton->out != NULL) {
      v8::Local<v8::Array> owners = Nan::New<Array>(0);
          Nan::Set(
          owners,
          Nan::New<v8::Number>(owners->Length()),
          Nan::To<v8::Object>(GitRepository::New(
            git_remote_owner(baton->out),
            true
          )).ToLocalChecked()
        );
         v8ConversionSlot = GitRemote::New(
        baton->out,
        true
          , owners
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
        
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method createWithOpts has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createWithOpts").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method createWithOpts has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.createWithOpts").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

        free(baton->out);
  }


  delete baton;
}

  
/*
     * @param Buf callback
   */
NAN_METHOD(GitRemote::DefaultBranch) {

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  DefaultBranchBaton* baton = new DefaultBranchBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

      baton->out = (git_buf *)malloc(sizeof(git_buf ));
        baton->out->ptr = NULL;
        baton->out->size = baton->out->asize = 0;
        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  DefaultBranchWorker *worker = new DefaultBranchWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());

  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::DefaultBranchWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->out
          ,baton->remote
  );

  return lockMaster;
}

void GitRemote::DefaultBranchWorker::Execute() {
  git_error_clear();

    int result = git_remote_default_branch(
baton->out,baton->remote  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::DefaultBranchWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.defaultBranch").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

        git_buf_dispose(baton->out);
        free((void *)baton->out);

  delete baton;
}

void GitRemote::DefaultBranchWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
   if (baton->out) {
    v8ConversionSlot = Nan::New<v8::String>(baton->out->ptr, baton->out->size).ToLocalChecked();
  }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
     
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method defaultBranch has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.defaultBranch").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method defaultBranch has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.defaultBranch").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }

        git_buf_dispose(baton->out);
        free((void *)baton->out);

  delete baton;
}

  
/*
 * @param Repository repo
   * @param String name
     */
NAN_METHOD(GitRemote::Delete) {

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String name is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  DeleteBaton* baton = new DeleteBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
          baton->repo = from_repo;
// start convert_from_v8 block
  const char * from_name = NULL;

  Nan::Utf8String name(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_name = (const char *) malloc(name.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_name, *name, name.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_name) + name.length()), 0, 1);
// end convert_from_v8 block
          baton->name = from_name;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  DeleteWorker *worker = new DeleteWorker(baton, callback, cleanupHandles);

             worker->Reference<GitRepository>("repo", info[0]);
             worker->Reference("name", info[1]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::DeleteWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->repo
          ,baton->name
  );

  return lockMaster;
}

void GitRemote::DeleteWorker::Execute() {
  git_error_clear();

    int result = git_remote_delete(
baton->repo,baton->name  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::DeleteWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.delete").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }


  delete baton;
}

void GitRemote::DeleteWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> result = Nan::Undefined();
     
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method delete has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.delete").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method delete has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.delete").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }


  delete baton;
}

  
/*
     */
NAN_METHOD(GitRemote::Disconnect) {

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  DisconnectBaton* baton = new DisconnectBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  DisconnectWorker *worker = new DisconnectWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());

  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::DisconnectWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->remote
  );

  return lockMaster;
}

void GitRemote::DisconnectWorker::Execute() {
  git_error_clear();

    int result = git_remote_disconnect(
baton->remote  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::DisconnectWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.disconnect").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }


  delete baton;
}

void GitRemote::DisconnectWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> result = Nan::Undefined();
   
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method disconnect has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.disconnect").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method disconnect has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.disconnect").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }


  delete baton;
}

  
/*
   * @param Strarray refspecs
   * @param FetchOptions opts
     */
NAN_METHOD(GitRemote::Download) {

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  DownloadBaton* baton = new DownloadBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();
// start convert_from_v8 block
  const git_strarray * from_refspecs = NULL;

  from_refspecs = StrArrayConverter::Convert(info[0]);
// end convert_from_v8 block
          baton->refspecs = from_refspecs;
          if (info[1]->IsNull() || info[1]->IsUndefined()) {
            baton->opts = nullptr;
          } else
            {
            auto conversionResult = ConfigurableGitFetchOptions::fromJavascript(nodegitContext, info[1]);
            if (!conversionResult.result) {
              return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked());
            }

            auto convertedObject = conversionResult.result;
            cleanupHandles["opts"] = convertedObject;
            baton->opts = convertedObject->GetValue();
          }
 
  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  DownloadWorker *worker = new DownloadWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());
           worker->Reference("refspecs", info[0]);
            worker->Reference("opts", info[1]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::DownloadWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->remote
          ,baton->refspecs
          ,baton->opts
  );

  return lockMaster;
}

void GitRemote::DownloadWorker::Execute() {
  git_error_clear();

    int result = git_remote_download(
baton->remote,baton->refspecs,baton->opts  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::DownloadWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.download").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }


  delete baton;
}

void GitRemote::DownloadWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> result = Nan::Undefined();
        
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method download has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.download").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method download has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.download").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }


  delete baton;
}

  
/*
     * @param Remote callback
   */
NAN_METHOD(GitRemote::Dup) {

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  DupBaton* baton = new DupBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

        baton->source = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  DupWorker *worker = new DupWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("source", info.This());

  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::DupWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->source
  );

  return lockMaster;
}

void GitRemote::DupWorker::Execute() {
  git_error_clear();

    int result = git_remote_dup(
&baton->dest,baton->source  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::DupWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.dup").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

      free(baton->dest);

  delete baton;
}

void GitRemote::DupWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (baton->dest != NULL) {
      v8::Local<v8::Array> owners = Nan::New<Array>(0);
          Nan::Set(
          owners,
          Nan::New<v8::Number>(owners->Length()),
          Nan::To<v8::Object>(GitRepository::New(
            git_remote_owner(baton->dest),
            true
          )).ToLocalChecked()
        );
         v8ConversionSlot = GitRemote::New(
        baton->dest,
        true
          , owners
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
     
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method dup has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.dup").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method dup has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.dup").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

        free(baton->dest);
  }


  delete baton;
}

  
/*
   * @param Strarray refspecs
   * @param FetchOptions opts
   * @param String reflog_message
     */
NAN_METHOD(GitRemote::Fetch) {

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  FetchBaton* baton = new FetchBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();
// start convert_from_v8 block
  const git_strarray * from_refspecs = NULL;

  from_refspecs = StrArrayConverter::Convert(info[0]);
// end convert_from_v8 block
          baton->refspecs = from_refspecs;
          if (info[1]->IsNull() || info[1]->IsUndefined()) {
            baton->opts = nullptr;
          } else
            {
            auto conversionResult = ConfigurableGitFetchOptions::fromJavascript(nodegitContext, info[1]);
            if (!conversionResult.result) {
              return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked());
            }

            auto convertedObject = conversionResult.result;
            cleanupHandles["opts"] = convertedObject;
            baton->opts = convertedObject->GetValue();
          }
 // start convert_from_v8 block
  const char * from_reflog_message = NULL;
    if ((info.Length() - 1) > 2 && info[2]->IsString()) {

  Nan::Utf8String reflog_message(Nan::To<v8::String>(info[2]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_reflog_message = (const char *) malloc(reflog_message.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_reflog_message, *reflog_message, reflog_message.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_reflog_message) + reflog_message.length()), 0, 1);
  }
  else {
    from_reflog_message = 0;
  }
// end convert_from_v8 block
          baton->reflog_message = from_reflog_message;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  FetchWorker *worker = new FetchWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());
           worker->Reference("refspecs", info[0]);
            worker->Reference("opts", info[1]);
            worker->Reference("reflog_message", info[2]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::FetchWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->remote
          ,baton->refspecs
          ,baton->opts
          ,baton->reflog_message
  );

  return lockMaster;
}

void GitRemote::FetchWorker::Execute() {
  git_error_clear();

    int result = git_remote_fetch(
baton->remote,baton->refspecs,baton->opts,baton->reflog_message  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::FetchWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.fetch").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }


  delete baton;
}

void GitRemote::FetchWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> result = Nan::Undefined();
          
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method fetch has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.fetch").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method fetch has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.fetch").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }


  delete baton;
}

  
/*
     * @param Array callback
   */
NAN_METHOD(GitRemote::GetFetchRefspecs) {

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  GetFetchRefspecsBaton* baton = new GetFetchRefspecsBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

      baton->array = (git_strarray *)malloc(sizeof(git_strarray ));
        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  GetFetchRefspecsWorker *worker = new GetFetchRefspecsWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());

  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::GetFetchRefspecsWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->array
          ,baton->remote
  );

  return lockMaster;
}

void GitRemote::GetFetchRefspecsWorker::Execute() {
  git_error_clear();

    int result = git_remote_get_fetch_refspecs(
baton->array,baton->remote  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::GetFetchRefspecsWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.getFetchRefspecs").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

        free((void*)baton->array);

  delete baton;
}

void GitRemote::GetFetchRefspecsWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    v8::Local<Array> tmpArray = Nan::New<Array>(baton->array->count);
    for (unsigned int i = 0; i < baton->array->count; i++) {
      Nan::Set(tmpArray, Nan::New<Number>(i), Nan::New<v8::String>(baton->array->strings[i]).ToLocalChecked());
    }
 
  v8ConversionSlot = tmpArray;
 // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
     
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method getFetchRefspecs has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.getFetchRefspecs").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method getFetchRefspecs has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.getFetchRefspecs").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

          free((void*)baton->array);
  }


  delete baton;
}

  
/*
     * @param Array callback
   */
NAN_METHOD(GitRemote::GetPushRefspecs) {

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  GetPushRefspecsBaton* baton = new GetPushRefspecsBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

      baton->array = (git_strarray *)malloc(sizeof(git_strarray ));
        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  GetPushRefspecsWorker *worker = new GetPushRefspecsWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());

  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::GetPushRefspecsWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->array
          ,baton->remote
  );

  return lockMaster;
}

void GitRemote::GetPushRefspecsWorker::Execute() {
  git_error_clear();

    int result = git_remote_get_push_refspecs(
baton->array,baton->remote  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::GetPushRefspecsWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.getPushRefspecs").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

        free((void*)baton->array);

  delete baton;
}

void GitRemote::GetPushRefspecsWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    v8::Local<Array> tmpArray = Nan::New<Array>(baton->array->count);
    for (unsigned int i = 0; i < baton->array->count; i++) {
      Nan::Set(tmpArray, Nan::New<Number>(i), Nan::New<v8::String>(baton->array->strings[i]).ToLocalChecked());
    }
 
  v8ConversionSlot = tmpArray;
 // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
     
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method getPushRefspecs has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.getPushRefspecs").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method getPushRefspecs has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.getPushRefspecs").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

          free((void*)baton->array);
  }


  delete baton;
}

   
/*
   * @param Number n
     * @return Refspec  result    */
NAN_METHOD(GitRemote::GetRefspec) {
  Nan::EscapableHandleScope scope;

  if (info.Length() == 0 || !info[0]->IsNumber()) {
    return Nan::ThrowError("Number n is required.");
  }

// start convert_from_v8 block
  size_t from_n;
      from_n = (size_t)   info[0].As<v8::Number>()->Value();
// end convert_from_v8 block

  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 const git_refspec * result =     git_remote_get_refspec(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
,          from_n
    );

        // null checks on pointers
        if (!result) {
          return info.GetReturnValue().Set(scope.Escape(Nan::Undefined()));
        }

      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (result != NULL) {
      v8::Local<v8::Array> owners = Nan::New<Array>(0);
            Nan::Set(owners, owners->Length(), info.This());
          v8ConversionSlot = GitRefspec::New(
        result,
        false
          , owners
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
 * @param String remote_name
     * @return Number  result    */
NAN_METHOD(GitRemote::IsValidName) {
  Nan::EscapableHandleScope scope;

  if (info.Length() == 0 || !info[0]->IsString()) {
    return Nan::ThrowError("String remote_name is required.");
  }

// start convert_from_v8 block
  const char * from_remote_name = NULL;

  Nan::Utf8String remote_name(Nan::To<v8::String>(info[0]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_remote_name = (const char *) malloc(remote_name.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_remote_name, *remote_name, remote_name.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_remote_name) + remote_name.length()), 0, 1);
// end convert_from_v8 block

  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              from_remote_name
    );

 int result =     git_remote_is_valid_name(
          from_remote_name
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
  
/*
  * @param Repository repo
    * @param Array callback
   */
NAN_METHOD(GitRemote::List) {

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  ListBaton* baton = new ListBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

      baton->out = (git_strarray *)malloc(sizeof(git_strarray ));
// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
          baton->repo = from_repo;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  ListWorker *worker = new ListWorker(baton, callback, cleanupHandles);

             worker->Reference<GitRepository>("repo", info[0]);
  
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::ListWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->out
          ,baton->repo
  );

  return lockMaster;
}

void GitRemote::ListWorker::Execute() {
  git_error_clear();

    int result = git_remote_list(
baton->out,baton->repo  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::ListWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.list").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

        free((void*)baton->out);

  delete baton;
}

void GitRemote::ListWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    v8::Local<Array> tmpArray = Nan::New<Array>(baton->out->count);
    for (unsigned int i = 0; i < baton->out->count; i++) {
      Nan::Set(tmpArray, Nan::New<Number>(i), Nan::New<v8::String>(baton->out->strings[i]).ToLocalChecked());
    }
 
  v8ConversionSlot = tmpArray;
 // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
     
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method list has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.list").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method list has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.list").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

          free((void*)baton->out);
  }


  delete baton;
}

  
/*
  * @param Repository repo
   * @param String name
    * @param Remote callback
   */
NAN_METHOD(GitRemote::Lookup) {

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String name is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  LookupBaton* baton = new LookupBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
          baton->repo = from_repo;
// start convert_from_v8 block
  const char * from_name = NULL;

  Nan::Utf8String name(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_name = (const char *) malloc(name.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_name, *name, name.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_name) + name.length()), 0, 1);
// end convert_from_v8 block
          baton->name = from_name;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  LookupWorker *worker = new LookupWorker(baton, callback, cleanupHandles);

             worker->Reference<GitRepository>("repo", info[0]);
             worker->Reference("name", info[1]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::LookupWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->repo
          ,baton->name
  );

  return lockMaster;
}

void GitRemote::LookupWorker::Execute() {
  git_error_clear();

    int result = git_remote_lookup(
&baton->out,baton->repo,baton->name  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::LookupWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.lookup").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

      git_remote_free(baton->out);

  delete baton;
}

void GitRemote::LookupWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (baton->out != NULL) {
      v8::Local<v8::Array> owners = Nan::New<Array>(0);
          Nan::Set(
          owners,
          Nan::New<v8::Number>(owners->Length()),
          Nan::To<v8::Object>(GitRepository::New(
            git_remote_owner(baton->out),
            true
          )).ToLocalChecked()
        );
         v8ConversionSlot = GitRemote::New(
        baton->out,
        true
          , owners
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
       
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method lookup has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.lookup").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method lookup has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.lookup").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

        git_remote_free(baton->out);
  }


  delete baton;
}

   
/*
     * @return String  result    */
NAN_METHOD(GitRemote::Name) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 const char * result =     git_remote_name(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

        // null checks on pointers
        if (!result) {
          return info.GetReturnValue().Set(scope.Escape(Nan::Undefined()));
        }

      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
  if (result){
       v8ConversionSlot = Nan::New<v8::String>(result).ToLocalChecked();
   }
  else {
    v8ConversionSlot = Nan::Null();
  }

  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
 * @param Number valid
   * @param String remote_name
     * @return Number  result    */
NAN_METHOD(GitRemote::NameIsValid) {
  Nan::EscapableHandleScope scope;

  if (info.Length() == 0 || !info[0]->IsNumber()) {
    return Nan::ThrowError("Number valid is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String remote_name is required.");
  }

// start convert_from_v8 block
  int * from_valid = NULL;
      *from_valid = (int)   info[0].As<v8::Number>()->Value();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_remote_name = NULL;

  Nan::Utf8String remote_name(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_remote_name = (const char *) malloc(remote_name.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_remote_name, *remote_name, remote_name.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_remote_name) + remote_name.length()), 0, 1);
// end convert_from_v8 block

  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              from_valid
            ,
              from_remote_name
    );

 int result =     git_remote_name_is_valid(
          from_valid
,          from_remote_name
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
     * @return Repository  result    */
NAN_METHOD(GitRemote::Owner) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 git_repository * result =     git_remote_owner(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

        // null checks on pointers
        if (!result) {
          return info.GetReturnValue().Set(scope.Escape(Nan::Undefined()));
        }

      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (result != NULL) {
        v8ConversionSlot = GitRepository::New(
        result,
        true
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
  
/*
   * @param RemoteCallbacks callbacks
     */
NAN_METHOD(GitRemote::Prune) {

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  PruneBaton* baton = new PruneBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();
          if (info[0]->IsNull() || info[0]->IsUndefined()) {
            baton->callbacks = nullptr;
          } else
            {
            auto conversionResult = ConfigurableGitRemoteCallbacks::fromJavascript(nodegitContext, info[0]);
            if (!conversionResult.result) {
              return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked());
            }

            auto convertedObject = conversionResult.result;
            cleanupHandles["callbacks"] = convertedObject;
            baton->callbacks = convertedObject->GetValue();
          }
 
  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  PruneWorker *worker = new PruneWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());
           worker->Reference("callbacks", info[0]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::PruneWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->remote
          ,baton->callbacks
  );

  return lockMaster;
}

void GitRemote::PruneWorker::Execute() {
  git_error_clear();

    int result = git_remote_prune(
baton->remote,baton->callbacks  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::PruneWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.prune").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }


  delete baton;
}

void GitRemote::PruneWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> result = Nan::Undefined();
      
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method prune has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.prune").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method prune has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.prune").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }


  delete baton;
}

   
/*
     * @return Number  result    */
NAN_METHOD(GitRemote::PruneRefs) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 int result =     git_remote_prune_refs(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
  
/*
   * @param Strarray refspecs
   * @param PushOptions opts
     */
NAN_METHOD(GitRemote::Push) {

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  PushBaton* baton = new PushBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();
// start convert_from_v8 block
  const git_strarray * from_refspecs = NULL;

  from_refspecs = StrArrayConverter::Convert(info[0]);
// end convert_from_v8 block
          baton->refspecs = from_refspecs;
          if (info[1]->IsNull() || info[1]->IsUndefined()) {
            baton->opts = nullptr;
          } else
            {
            auto conversionResult = ConfigurableGitPushOptions::fromJavascript(nodegitContext, info[1]);
            if (!conversionResult.result) {
              return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked());
            }

            auto convertedObject = conversionResult.result;
            cleanupHandles["opts"] = convertedObject;
            baton->opts = convertedObject->GetValue();
          }
 
  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  PushWorker *worker = new PushWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());
           worker->Reference("refspecs", info[0]);
            worker->Reference("opts", info[1]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::PushWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->remote
          ,baton->refspecs
          ,baton->opts
  );

  return lockMaster;
}

void GitRemote::PushWorker::Execute() {
  git_error_clear();

    int result = git_remote_push(
baton->remote,baton->refspecs,baton->opts  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::PushWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.push").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }


  delete baton;
}

void GitRemote::PushWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> result = Nan::Undefined();
        
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method push has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.push").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method push has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.push").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }


  delete baton;
}

   
/*
     * @return String  result    */
NAN_METHOD(GitRemote::Pushurl) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 const char * result =     git_remote_pushurl(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

        // null checks on pointers
        if (!result) {
          return info.GetReturnValue().Set(scope.Escape(Nan::Undefined()));
        }

      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
  if (result){
       v8ConversionSlot = Nan::New<v8::String>(result).ToLocalChecked();
   }
  else {
    v8ConversionSlot = Nan::Null();
  }

  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
     * @return Number  result    */
NAN_METHOD(GitRemote::RefspecCount) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 size_t result =     git_remote_refspec_count(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
  
/*
  * @param Repository repo
   * @param String name
   * @param String new_name
    * @param Array callback
   */
NAN_METHOD(GitRemote::Rename) {

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String name is required.");
  }

  if (info.Length() == 2 || !info[2]->IsString()) {
    return Nan::ThrowError("String new_name is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  RenameBaton* baton = new RenameBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

      baton->problems = (git_strarray *)malloc(sizeof(git_strarray ));
// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
          baton->repo = from_repo;
// start convert_from_v8 block
  const char * from_name = NULL;

  Nan::Utf8String name(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_name = (const char *) malloc(name.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_name, *name, name.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_name) + name.length()), 0, 1);
// end convert_from_v8 block
          baton->name = from_name;
// start convert_from_v8 block
  const char * from_new_name = NULL;

  Nan::Utf8String new_name(Nan::To<v8::String>(info[2]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_new_name = (const char *) malloc(new_name.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_new_name, *new_name, new_name.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_new_name) + new_name.length()), 0, 1);
// end convert_from_v8 block
          baton->new_name = from_new_name;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  RenameWorker *worker = new RenameWorker(baton, callback, cleanupHandles);

             worker->Reference<GitRepository>("repo", info[0]);
             worker->Reference("name", info[1]);
            worker->Reference("new_name", info[2]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::RenameWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->problems
          ,baton->repo
          ,baton->name
          ,baton->new_name
  );

  return lockMaster;
}

void GitRemote::RenameWorker::Execute() {
  git_error_clear();

    int result = git_remote_rename(
baton->problems,baton->repo,baton->name,baton->new_name  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::RenameWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.rename").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

        free((void*)baton->problems);

  delete baton;
}

void GitRemote::RenameWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    v8::Local<Array> tmpArray = Nan::New<Array>(baton->problems->count);
    for (unsigned int i = 0; i < baton->problems->count; i++) {
      Nan::Set(tmpArray, Nan::New<Number>(i), Nan::New<v8::String>(baton->problems->strings[i]).ToLocalChecked());
    }
 
  v8ConversionSlot = tmpArray;
 // end convert_to_v8 block
      v8::Local<v8::Value> result = v8ConversionSlot;
         
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method rename has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.rename").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method rename has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.rename").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

          free((void*)baton->problems);
  }


  delete baton;
}

   
/*
 * @param Repository repo
   * @param String remote
   * @param Number value
     * @return Number  result    */
NAN_METHOD(GitRemote::SetAutotag) {
  Nan::EscapableHandleScope scope;

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String remote is required.");
  }

  if (info.Length() == 2 || !info[2]->IsNumber()) {
    return Nan::ThrowError("Number value is required.");
  }

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_remote = NULL;

  Nan::Utf8String remote(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_remote = (const char *) malloc(remote.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_remote, *remote, remote.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_remote) + remote.length()), 0, 1);
// end convert_from_v8 block
// start convert_from_v8 block
  git_remote_autotag_option_t from_value;
      from_value = (git_remote_autotag_option_t)  (int) info[2].As<v8::Number>()->Value();
// end convert_from_v8 block

  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              from_repo
            ,
              from_remote
    );

 int result =     git_remote_set_autotag(
          from_repo
,          from_remote
,          from_value
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
 * @param Repository repo
   * @param String remote
   * @param String url
     * @return Number  result    */
NAN_METHOD(GitRemote::SetPushurl) {
  Nan::EscapableHandleScope scope;

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String remote is required.");
  }

  if (info.Length() == 2 || !info[2]->IsString()) {
    return Nan::ThrowError("String url is required.");
  }

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_remote = NULL;

  Nan::Utf8String remote(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_remote = (const char *) malloc(remote.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_remote, *remote, remote.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_remote) + remote.length()), 0, 1);
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_url = NULL;

  Nan::Utf8String url(Nan::To<v8::String>(info[2]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_url = (const char *) malloc(url.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_url, *url, url.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_url) + url.length()), 0, 1);
// end convert_from_v8 block

  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              from_repo
            ,
              from_remote
            ,
              from_url
    );

 int result =     git_remote_set_pushurl(
          from_repo
,          from_remote
,          from_url
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
 * @param Repository repo
   * @param String remote
   * @param String url
     * @return Number  result    */
NAN_METHOD(GitRemote::SetUrl) {
  Nan::EscapableHandleScope scope;

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("Repository repo is required.");
  }

  if (info.Length() == 1 || !info[1]->IsString()) {
    return Nan::ThrowError("String remote is required.");
  }

  if (info.Length() == 2 || !info[2]->IsString()) {
    return Nan::ThrowError("String url is required.");
  }

// start convert_from_v8 block
  git_repository * from_repo = NULL;
from_repo = Nan::ObjectWrap::Unwrap<GitRepository>(Nan::To<v8::Object>(info[0]).ToLocalChecked())->GetValue();
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_remote = NULL;

  Nan::Utf8String remote(Nan::To<v8::String>(info[1]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_remote = (const char *) malloc(remote.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_remote, *remote, remote.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_remote) + remote.length()), 0, 1);
// end convert_from_v8 block
// start convert_from_v8 block
  const char * from_url = NULL;

  Nan::Utf8String url(Nan::To<v8::String>(info[2]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_url = (const char *) malloc(url.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_url, *url, url.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_url) + url.length()), 0, 1);
// end convert_from_v8 block

  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              from_repo
            ,
              from_remote
            ,
              from_url
    );

 int result =     git_remote_set_url(
          from_repo
,          from_remote
,          from_url
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
     * @return IndexerProgress  result    */
NAN_METHOD(GitRemote::Stats) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 const git_indexer_progress * result =     git_remote_stats(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

        // null checks on pointers
        if (!result) {
          return info.GetReturnValue().Set(scope.Escape(Nan::Undefined()));
        }

      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
    if (result != NULL) {
      v8::Local<v8::Array> owners = Nan::New<Array>(0);
            Nan::Set(owners, owners->Length(), info.This());
          v8ConversionSlot = GitIndexerProgress::New(
        result,
        false
          , owners
       );
   }
  else {
    v8ConversionSlot = Nan::Null();
  }
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
   
/*
     * @return Number  result    */
NAN_METHOD(GitRemote::Stop) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 int result =     git_remote_stop(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );


      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
     v8ConversionSlot = Nan::New<Number>( result);
  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
  
/*
   * @param RemoteCallbacks callbacks
   * @param Number update_fetchhead
   * @param Number download_tags
   * @param String reflog_message
     */
NAN_METHOD(GitRemote::UpdateTips) {

  if (info.Length() == 0 || !info[0]->IsObject()) {
    return Nan::ThrowError("RemoteCallbacks callbacks is required.");
  }

  if (info.Length() == 1 || !info[1]->IsNumber()) {
    return Nan::ThrowError("Number update_fetchhead is required.");
  }

  if (info.Length() == 2 || !info[2]->IsNumber()) {
    return Nan::ThrowError("Number download_tags is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  UpdateTipsBaton* baton = new UpdateTipsBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();
            {
            auto conversionResult = ConfigurableGitRemoteCallbacks::fromJavascript(nodegitContext, info[0]);
            if (!conversionResult.result) {
              return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked());
            }

            auto convertedObject = conversionResult.result;
            cleanupHandles["callbacks"] = convertedObject;
            baton->callbacks = convertedObject->GetValue();
          }
 // start convert_from_v8 block
  int from_update_fetchhead;
      from_update_fetchhead = (int)   info[1].As<v8::Number>()->Value();
// end convert_from_v8 block
          baton->update_fetchhead = from_update_fetchhead;
// start convert_from_v8 block
  git_remote_autotag_option_t from_download_tags;
      from_download_tags = (git_remote_autotag_option_t)  (int) info[2].As<v8::Number>()->Value();
// end convert_from_v8 block
          baton->download_tags = from_download_tags;
// start convert_from_v8 block
  const char * from_reflog_message = NULL;
    if ((info.Length() - 1) > 3 && info[3]->IsString()) {

  Nan::Utf8String reflog_message(Nan::To<v8::String>(info[3]).ToLocalChecked());
  // malloc with one extra byte so we can add the terminating null character C-strings expect:
  from_reflog_message = (const char *) malloc(reflog_message.length() + 1);
  // copy the characters from the nodejs string into our C-string (used instead of strdup or strcpy because nulls in
  // the middle of strings are valid coming from nodejs):
  memcpy((void *)from_reflog_message, *reflog_message, reflog_message.length());
  // ensure the final byte of our new string is null, extra casts added to ensure compatibility with various C types
  // used in the nodejs binding generation:
  memset((void *)(((char *)from_reflog_message) + reflog_message.length()), 0, 1);
  }
  else {
    from_reflog_message = 0;
  }
// end convert_from_v8 block
          baton->reflog_message = from_reflog_message;

  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  UpdateTipsWorker *worker = new UpdateTipsWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());
           worker->Reference("callbacks", info[0]);
            worker->Reference("update_fetchhead", info[1]);
            worker->Reference("download_tags", info[2]);
            worker->Reference("reflog_message", info[3]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::UpdateTipsWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->remote
          ,baton->callbacks
          ,baton->reflog_message
  );

  return lockMaster;
}

void GitRemote::UpdateTipsWorker::Execute() {
  git_error_clear();

    int result = git_remote_update_tips(
baton->remote,baton->callbacks,baton->update_fetchhead,baton->download_tags,baton->reflog_message  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::UpdateTipsWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.updateTips").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }


  delete baton;
}

void GitRemote::UpdateTipsWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> result = Nan::Undefined();
            
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method updateTips has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.updateTips").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method updateTips has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.updateTips").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }


  delete baton;
}

  
/*
   * @param Strarray refspecs
   * @param PushOptions opts
     */
NAN_METHOD(GitRemote::Upload) {

  if (info.Length() == 1 || !info[1]->IsObject()) {
    return Nan::ThrowError("PushOptions opts is required.");
  }

  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  UploadBaton* baton = new UploadBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;


  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;

        baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();
// start convert_from_v8 block
  const git_strarray * from_refspecs = NULL;

  from_refspecs = StrArrayConverter::Convert(info[0]);
// end convert_from_v8 block
          baton->refspecs = from_refspecs;
            {
            auto conversionResult = ConfigurableGitPushOptions::fromJavascript(nodegitContext, info[1]);
            if (!conversionResult.result) {
              return Nan::ThrowError(Nan::New(conversionResult.error).ToLocalChecked());
            }

            auto convertedObject = conversionResult.result;
            cleanupHandles["opts"] = convertedObject;
            baton->opts = convertedObject->GetValue();
          }
 
  Nan::Callback *callback = new Nan::Callback(v8::Local<Function>::Cast(info[info.Length() - 1]));
  UploadWorker *worker = new UploadWorker(baton, callback, cleanupHandles);

        worker->Reference<GitRemote>("remote", info.This());
           worker->Reference("refspecs", info[0]);
            worker->Reference("opts", info[1]);
 
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::UploadWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(
    /*asyncAction: */true
          ,baton->remote
          ,baton->refspecs
          ,baton->opts
  );

  return lockMaster;
}

void GitRemote::UploadWorker::Execute() {
  git_error_clear();

    int result = git_remote_upload(
baton->remote,baton->refspecs,baton->opts  );

      baton->error_code = result;

      if (result != GIT_OK && git_error_last() != NULL) {
        baton->error = git_error_dup(git_error_last());
      }

}

void GitRemote::UploadWorker::HandleErrorCallback() {
  if (!GetIsCancelled()) {
    v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error(ErrorMessage())).ToLocalChecked();
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.upload").ToLocalChecked());
    v8::Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }

  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }


  delete baton;
}

void GitRemote::UploadWorker::HandleOKCallback() {
    if (baton->error_code == GIT_OK) {
    v8::Local<v8::Value> result = Nan::Undefined();
        
    v8::Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  } else {
    if (baton->error) {
      v8::Local<v8::Object> err;
      if (baton->error->message) {
        err = Nan::To<v8::Object>(Nan::Error(baton->error->message)).ToLocalChecked();
      } else {
        err = Nan::To<v8::Object>(Nan::Error("Method upload has thrown an error.")).ToLocalChecked();
      }
      Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
      Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.upload").ToLocalChecked());
      v8::Local<v8::Value> argv[1] = {
        err
      };
      callback->Call(1, argv, async_resource);
      if (baton->error->message)
        free((void *)baton->error->message);
      free((void *)baton->error);
    } else if (baton->error_code < 0) {
      bool callbackFired = false;
      if (!callbackErrorHandle.IsEmpty()) {
        v8::Local<v8::Value> maybeError = Nan::New(callbackErrorHandle);
        if (!maybeError->IsNull() && !maybeError->IsUndefined()) {
          v8::Local<v8::Value> argv[1] = {
            maybeError
          };
          callback->Call(1, argv, async_resource);
          callbackFired = true;
        }
      }

      if (!callbackFired) {
        v8::Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Method upload has thrown an error.")).ToLocalChecked();
        Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
        Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.upload").ToLocalChecked());
        v8::Local<v8::Value> argv[1] = {
          err
        };
        callback->Call(1, argv, async_resource);
      }
    } else {
      callback->Call(0, NULL, async_resource);
    }

  }


  delete baton;
}

   
/*
     * @return String  result    */
NAN_METHOD(GitRemote::Url) {
  Nan::EscapableHandleScope scope;


  git_error_clear();

  { // lock master scope start
    nodegit::LockMaster lockMaster(
      /*asyncAction: */false
            ,
              Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

 const char * result =     git_remote_url(
          Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue()
    );

        // null checks on pointers
        if (!result) {
          return info.GetReturnValue().Set(scope.Escape(Nan::Undefined()));
        }

      v8::Local<v8::Value> v8ConversionSlot;
// start convert_to_v8 block
  if (result){
       v8ConversionSlot = Nan::New<v8::String>(result).ToLocalChecked();
   }
  else {
    v8ConversionSlot = Nan::Null();
  }

  // end convert_to_v8 block
        return info.GetReturnValue().Set(scope.Escape(v8ConversionSlot));
  }
}
        NAN_METHOD(GitRemote::ReferenceList)
{
  if (!info[info.Length() - 1]->IsFunction()) {
    return Nan::ThrowError("Callback is required and must be a Function.");
  }

  ReferenceListBaton* baton = new ReferenceListBaton();

  baton->error_code = GIT_OK;
  baton->error = NULL;
  baton->out = new std::vector<git_remote_head*>;
  baton->remote = Nan::ObjectWrap::Unwrap<GitRemote>(info.This())->GetValue();

  Nan::Callback *callback = new Nan::Callback(Local<Function>::Cast(info[info.Length() - 1]));
  std::map<std::string, std::shared_ptr<nodegit::CleanupHandle>> cleanupHandles;
  ReferenceListWorker *worker = new ReferenceListWorker(baton, callback, cleanupHandles);
  worker->Reference<GitRemote>("remote", info.This());
  nodegit::Context *nodegitContext = reinterpret_cast<nodegit::Context *>(info.Data().As<External>()->Value());
  nodegitContext->QueueWorker(worker);
  return;
}

nodegit::LockMaster GitRemote::ReferenceListWorker::AcquireLocks() {
  nodegit::LockMaster lockMaster(true, baton->remote);
  return lockMaster;
}

void GitRemote::ReferenceListWorker::Execute()
{
  git_error_clear();

  const git_remote_head **remote_heads;
  size_t num_remote_heads;
  baton->error_code = git_remote_ls(
    &remote_heads,
    &num_remote_heads,
    baton->remote
  );

  if (baton->error_code != GIT_OK) {
    baton->error = git_error_dup(git_error_last());
    delete baton->out;
    baton->out = NULL;
    return;
  }

  baton->out->reserve(num_remote_heads);

  for (size_t head_index = 0; head_index < num_remote_heads; ++head_index) {
    git_remote_head *remote_head = git_remote_head_dup(remote_heads[head_index]);
    baton->out->push_back(remote_head);
  }
}

void GitRemote::ReferenceListWorker::HandleErrorCallback() {
  if (baton->error) {
    if (baton->error->message) {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }

  delete baton->out;

  delete baton;
}

void GitRemote::ReferenceListWorker::HandleOKCallback()
{
  if (baton->out != NULL)
  {
    unsigned int size = baton->out->size();
    Local<Array> result = Nan::New<Array>(size);
    for (unsigned int i = 0; i < size; i++) {
      Nan::Set(result, Nan::New<Number>(i), GitRemoteHead::New(baton->out->at(i), true));
    }

    delete baton->out;

    Local<v8::Value> argv[2] = {
      Nan::Null(),
      result
    };
    callback->Call(2, argv, async_resource);
  }
  else if (baton->error)
  {
    Local<v8::Value> argv[1] = {
      Nan::Error(baton->error->message)
    };
    callback->Call(1, argv, async_resource);
    if (baton->error->message)
    {
      free((void *)baton->error->message);
    }

    free((void *)baton->error);
  }
  else if (baton->error_code < 0)
  {
    Local<v8::Object> err = Nan::To<v8::Object>(Nan::Error("Reference List has thrown an error.")).ToLocalChecked();
    Nan::Set(err, Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
    Nan::Set(err, Nan::New("errorFunction").ToLocalChecked(), Nan::New("Remote.referenceList").ToLocalChecked());
    Local<v8::Value> argv[1] = {
      err
    };
    callback->Call(1, argv, async_resource);
  }
  else
  {
    callback->Call(0, NULL, async_resource);
  }

  delete baton;
}

    // force base class template instantiation, to make sure we get all the
// methods, statics, etc.
template class NodeGitWrapper<GitRemoteTraits>;
 