/* This code is PUBLIC DOMAIN, and is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND. See the accompanying
* LICENSE file.
*/
#include <v8.h>
#include <node.h>
#include <stdlib.h>
#include "clientapi.h"
#include "basicuser.h"
#include <unistd.h>
#include <iostream>
#include <vector>
#include <string.h>
#include <string>
using namespace node;
using namespace v8;
class PerforceNodeApi: ObjectWrap
{
private:
int m_count;
BasicUser ui;
ClientApi client;
public:
static Persistent<FunctionTemplate> s_ct;
static void Init(Handle<Object> target)
{
HandleScope scope;
Local<FunctionTemplate> t = FunctionTemplate::New(New);
s_ct = Persistent<FunctionTemplate>::New(t);
s_ct->InstanceTemplate()->SetInternalFieldCount(1);
s_ct->SetClassName(String::NewSymbol("PerforceNodeApi"));
NODE_SET_PROTOTYPE_METHOD(s_ct, "run", Run);
target->Set(String::NewSymbol("PerforceNodeApi"),
s_ct->GetFunction());
}
PerforceNodeApi() :
m_count(0)
{
}
~PerforceNodeApi()
{
}
static Handle<Value> New(const Arguments& args)
{
HandleScope scope;
PerforceNodeApi* hw = new PerforceNodeApi();
int usetags = 1;
hw->Wrap(args.This());
Local<Object> params;
if (args.Length() > 0)
{
if (!args[0]->IsObject())
return ThrowException(Exception::TypeError(
String::New("Argument 0 must be an Object")));
else
params = Local<Object>::Cast(args[0]);
//* Override the environment P4 settings if parameters are set
if (params->HasOwnProperty(String::New("port"))) {
hw->client.SetPort(*String::Utf8Value(params->Get(String::New("port"))->ToString()));
}
if (params->HasOwnProperty(String::New("user"))) {
hw->client.SetUser(*String::Utf8Value(params->Get(String::New("user"))->ToString()));
}
if (params->HasOwnProperty(String::New("password"))) {
hw->client.SetPassword(*String::Utf8Value(params->Get(String::New("password"))->ToString()));
}
if (params->HasOwnProperty(String::New("client"))) {
hw->client.SetClient(*String::Utf8Value(params->Get(String::New("client"))->ToString()));
}
if (params->HasOwnProperty(String::New("json"))) {
char *json = *String::Utf8Value(params->Get(String::New("json"))->ToString());
if (!strcmp("false",json) || !strcmp("False",json) || !strcmp("FALSE",json)) {
usetags = 0;
}
}
}
if (usetags) {
hw->client.SetProtocol("tag", "");
}
return args.This();
}
struct p4_baton_t {
PerforceNodeApi *hw;
int increment_by;
int sleep_for;
Persistent<Function> cb;
char** myargv;
int myargc;
char *command;
char *inputData;
};
static Handle<Value> Run(const Arguments& args)
{
HandleScope scope;
Local<Array> cmd;
Local<String> inputString = String::New("",0);
Local<Function> cb;
if (args.Length() <=1)
return ThrowException(Exception::SyntaxError(String::New
("Not enough arguments. [expected: (cmd, cb) || (cmd,inpt,cb)]")));
if (!args[0]->IsArray())
return ThrowException(Exception::TypeError(
String::New("Argument 0 must be an Array")));
else
cmd = Local<Array>::Cast(args[0]);
if (args[1]->IsFunction())
cb = Local<Function>::Cast(args[1]);
else if (args[1]->IsString())
{
inputString = Local<String>::Cast(args[1]);
if (args[2]->IsFunction())
cb = Local<Function>::Cast(args[2]);
else
ThrowException(Exception::TypeError(
String::New("Argument 2 must be a Function")));
}
else
return ThrowException(Exception::TypeError(
String::New("Argument 1 must be a String or Function")));
int parmCount = cmd->Length();
char** argv;
int argc;
char *command;
char *inputData;
argv = new char*[parmCount-1];
argc = parmCount-1;
//std::cout<< "Run() cmd IsArray? " <<cmd->IsArray() << " length=" << cmd->Length()<<std::endl;
for (int i = 0 ; i < parmCount; i++) {
String::AsciiValue p (cmd->Get(v8::Number::New(i)));
//std::cout << i << " p: " << *p << " len: " << strlen(*p) << std::endl;
char* ap;
if ( i == 0) {
command = (char*)malloc(strlen(*p) + 1);
strcpy(command,*p);
}
else {
ap = (char*)malloc(strlen(*p) + 1);
strcpy(ap,*p);
argv[i-1] = ap;
//std::cout << i << " argv : " << argv[i-1] << " len: " << strlen(argv[i-1]) << std::endl;
}
}
String::AsciiValue cmdstr(cmd);
//std::cout << "Run .. cmd string " << *cmdstr << std::endl;
PerforceNodeApi* hw = ObjectWrap::Unwrap<PerforceNodeApi>(args.This());
p4_baton_t *baton = new p4_baton_t();
baton->hw = hw;
baton->increment_by = 2;
baton->sleep_for = 1;
baton->cb = Persistent<Function>::New(cb);
baton->myargv = argv;
baton->myargc = argc;
baton->command = command;
String::AsciiValue s (inputString);
inputData = (char*)malloc(strlen(*s)+1);
strcpy(inputData,*s);
baton->inputData = inputData;
hw->Ref();
uv_work_t *work_req = (uv_work_t *) (calloc(1, sizeof(uv_work_t)));
work_req->data = baton;
uv_queue_work(uv_default_loop(), work_req, EIO_P4, EIO_AfterP4);
return Undefined();
}
static void EIO_P4(uv_work_t *req)
{
Error e;
StrBuf msg;
char** argv;
int argc;
p4_baton_t *baton = static_cast<p4_baton_t *>(req->data);
baton->hw->m_count += baton->increment_by;
PerforceNodeApi *hw = baton->hw; // our class object
argv = new char*[argc];
argv = baton->myargv;
argc = baton->myargc;
char *command = baton->command;
//std::cout << " EIO_P4 command = " << command <<std::endl;
//for (int i = 0 ; i < argc; i++) {
// std::cout << " EIO_P4 argv : i = " << argv[i] <<std::endl;
//}
hw->client.Init( &e );
if( e.Test() )
{
e.Fmt( &msg );
fprintf( stderr, "client.Init %s\n", msg.Text() );
}
if (sizeof(baton->inputData)>0)
(&hw->ui)->SetInputData(baton->inputData);
hw->client.SetArgv( argc, argv );
hw->client.Run( command, &hw->ui );
// Clean up connection
hw->client.Final( &e );
if( e.Test() )
{
e.Fmt( &msg );
fprintf( stderr, "client.Final %s\n", msg.Text() );
}
return;
}
static void EIO_AfterP4(uv_work_t *req)
{
HandleScope scope;
p4_baton_t *baton = static_cast<p4_baton_t *>(req->data);
baton->hw->Unref();
Local<Value> argv[2];
// GetErr & GetInfo return the p4 command's err and/or data response(s) */
argv[0] = String::New(baton->hw->ui.GetErr());
argv[1] = String::New(baton->hw->ui.GetInfo());
//String::AsciiValue info(argv[0]);
//std::cout << " EIO_AfterP4 " << *info ;
TryCatch try_catch;
baton->cb->Call(Context::GetCurrent()->Global(), 2, argv);
if (try_catch.HasCaught()) {
FatalException(try_catch);
}
baton->cb.Dispose();
delete baton;
return;
}
};
Persistent<FunctionTemplate> PerforceNodeApi::s_ct;
extern "C" {
static void init (Handle<Object> target)
{
PerforceNodeApi::Init(target);
}
NODE_MODULE(perforce_nodeapi, init);
}
# |
Change |
User |
Description |
Committed |
|
#1
|
8163 |
Gary Gibbons |
Perforce Node Extension for public.perforce.com. |
|
|