/*
CVSNT Checkout trigger handler
Copyright (C) 2005 Tony Hoyle and March-Hare Software Ltd
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef _WIN32
#pragma warning(disable:4503) // Decorated name length warning
#endif
#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <process.h>
#include <winsock2.h>
#include <mapi.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_DIRECT_H
#include <direct.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#define MODULE checkout
#include <ctype.h>
#include <cvstools.h>
#include <map>
#include "../version.h"
#define CVSROOT_SHADOW "CVSROOT/shadow"
static bool g_verbose;
#ifndef _WIN32
static bool g_cifslogin;
#endif
cvs::filename g_repos;
cvs::string g_command;
std::map<cvs::filename, int> module_list;
std::map<cvs::string, int> tag_list;
#ifdef _WIN32
HMODULE g_hInst;
BOOL CALLBACK DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
g_hInst = hModule;
return TRUE;
}
#include "checkout_resource.h"
int win32config(const struct plugin_interface *ui, void *wnd);
#endif
int initcheckout(const struct trigger_interface_t* cb, const char *command, const char *date, const char *hostname, const char *username, const char *virtual_repository, const char *physical_repository, const char *sessionid, const char *editor, int count_uservar, const char **uservar, const char **userval, const char *client_version, const char *character_set)
{
char value[256];
int val = 0;
if(!CGlobalSettings::GetGlobalValue("cvsnt","Plugins","CheckoutTrigger",value,sizeof(value)))
val = atoi(value);
if(!val)
{
CServerIo::trace(3,"Checkout trigger not enabled.");
return -1;
}
else
{
CServerIo::trace(3,"Checkout trigger is enabled.");
}
#ifndef _WIN32
g_cifslogin = false;
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutLogin",value,sizeof(value)))
g_cifslogin = atoi(value)?true:false;
#endif
g_verbose = false;
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutVerbose",value,sizeof(value)))
g_verbose = atoi(value)?true:false;
g_repos = physical_repository;
g_command = command;
return 0;
}
int closecheckout(const struct trigger_interface_t* cb)
{
return 0;
}
int pretagcheckout(const struct trigger_interface_t* cb, const char *message, const char *directory, int name_list_count, const char **name_list, const char **version_list, char tag_type, const char *action, const char *tag)
{
module_list[directory]++;
if(tag && tag[0])
tag_list[tag]++;
else
tag_list["HEAD"]++;
return 0;
}
int verifymsgcheckout(const struct trigger_interface_t* cb, const char *directory, const char *filename)
{
return 0;
}
int loginfocheckout(const struct trigger_interface_t* cb, const char *message, const char *status, const char *directory, int change_list_count, change_info_t *change_list)
{
module_list[directory]++;
for(int n=0; n<change_list_count; n++)
{
if(change_list[n].tag)
tag_list[change_list[n].tag]++;
else
tag_list["HEAD"]++;
}
return 0;
}
int historycheckout(const struct trigger_interface_t* cb, char type, const char *workdir, const char *revs, const char *name, const char *bugid, const char *message)
{
return 0;
}
int notifycheckout(const struct trigger_interface_t* cb, const char *message, const char *bugid, const char *directory, const char *notify_user, const char *tag, const char *type, const char *file)
{
return 0;
}
int precommitcheckout(const struct trigger_interface_t* cb, int name_list_count, const char **name_list, const char *message, const char *directory)
{
return 0;
}
int postcommitcheckout(const struct trigger_interface_t* cb, const char *directory)
{
return 0;
}
int precommandcheckout(const struct trigger_interface_t* cb, int argc, const char **argv)
{
return 0;
}
static int outputProc(const char *str, size_t len, void * /*param*/)
{
if(g_verbose)
return CServerIo::output(len,str);
return 0;
}
static int errorProc(const char *str, size_t len, void * /*param*/)
{
if(g_verbose)
return CServerIo::error(len,str);
return 0;
}
int postcommandcheckout(const struct trigger_interface_t* cb, const char *directory)
{
cvs::filename fn;
CFileAccess acc;
cvs::string line;
if(g_command!="tag" && g_command!="rtag" && g_command!="commit")
return 0;
cvs::sprintf(fn,80,"%s/%s",g_repos.c_str(),CVSROOT_SHADOW);
if(!acc.open(fn.c_str(),"r"))
{
CServerIo::trace(3,"Could not open "CVSROOT_SHADOW);
return 0;
}
else
{
CServerIo::trace(3,"Opened "CVSROOT_SHADOW);
}
int linenum;
for(linenum=1; acc.getline(line); linenum++)
{
const char *p=line.c_str();
while(isspace((unsigned char)*p))
p++;
if(*p=='#')
continue;
CTokenLine tok(p);
if(tok.size()!=3)
{
CServerIo::error("Malformed line %d in "CVSROOT_SHADOW" - Need Module Tag Directory",linenum);
continue;
}
bool found = false;
cvs::string match;
for(std::map<cvs::filename,int>::const_iterator i = module_list.begin(); i!=module_list.end(); ++i)
{
CServerIo::trace(3,"Regexp match: %s - %s",tok[0],i->first.c_str());
cvs::wildcard_filename mod(i->first.c_str());
if(mod.matches_regexp(tok[0])) // Wildcard match
{
CServerIo::trace(3,"Match found!");
found=true;
match = i->first.c_str();
break;
}
}
if(!found)
continue;
found=false;
for(std::map<cvs::string,int>::const_iterator i = tag_list.begin(); i!=tag_list.end(); ++i)
{
if(!strcmp(i->first.c_str(),tok[1]))
{
found=true;
break;
}
}
if(!found)
continue;
#ifndef _WIN32
if(g_cifslogin)
{
CRunFile rf1;
char host[256],name[256]="cifslogin",user[256]="",password[256]="";
if(CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutLoginUser",user,sizeof(user)))
{
CServerIo::trace(3,"Checkout plugin: Login user name not set");
user[0]='\0';
}
if(CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutLoginPassword",password,sizeof(password)))
{
CServerIo::trace(3,"Checkout plugin: Login password not set");
password[0]='\0';
}
if(CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutLoginCommand",name,sizeof(name)))
{
CServerIo::trace(3,"Checkout plugin: Login command not set - assume \"cifslogin\"");
strcpy(name,"cifslogin");
}
if(CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutLoginServer",host,sizeof(host)))
{
CServerIo::trace(3,"Checkout plugin: Login server not set");
host[0]='\0';
}
if (*host)
{
rf1.setOutput(outputProc,NULL);
rf1.setError(errorProc,NULL);
rf1.addArg(name);
if (*password)
{
rf1.addArg("-P");
rf1.addArg(password);
}
rf1.addArg(host);
if (*user)
rf1.addArg(user);
if(!rf1.run(NULL))
{
CServerIo::error("Unable to run checkout login command");
return 0;
}
int ret;
rf1.wait(ret);
}
}
#endif
CRunFile rf;
char cvscmd[2048]="\0";
char cvsopt[2048]="\0";
char cvscmdopt[2048]="\0";
rf.setOutput(outputProc,NULL);
rf.setError(errorProc,NULL);
if(CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutCommand",cvscmd,sizeof(cvscmd)))
{
CServerIo::trace(3,"Checkout plugin: Command not set - usng default");
rf.addArg(CGlobalSettings::GetCvsCommand());
}
else
{
CServerIo::trace(3,"Checkout plugin: Using specified command");
rf.addArg(cvscmd);
}
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutOption",cvsopt,sizeof(cvsopt)))
{
CServerIo::trace(3,"Checkout plugin: Options set - %s",cvsopt);
rf.addArg(cvsopt);
}
rf.addArg("-d");
rf.addArg(g_repos.c_str());
rf.addArg("co");
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutCommandOption",cvscmdopt,sizeof(cvscmdopt)))
{
CServerIo::trace(3,"Checkout plugin: Command options set - %s",cvscmdopt);
rf.addArg(cvscmdopt);
}
rf.addArg("-d");
rf.addArg(tok[2]);
rf.addArg("-r");
rf.addArg(tok[1]);
rf.addArg(match.c_str());
if(!rf.run(NULL))
{
CServerIo::error("Unable to run cvs checkout");
return 0;
}
int ret;
rf.wait(ret);
}
return 0;
}
int premodulecheckout(const struct trigger_interface_t* cb, const char *module)
{
module_list[module]++;
return 0;
}
int postmodulecheckout(const struct trigger_interface_t* cb, const char *module)
{
module_list[module]++;
return 0;
}
int get_templatecheckout(const struct trigger_interface_t *cb, const char *directory, const char **template_ptr)
{
return 0;
}
int parse_keywordcheckout(const struct trigger_interface_t *cb, const char *keyword,const char *directory,const char *file,const char *branch,const char *author,const char *printable_date,const char *rcs_date,const char *locker,const char *state,const char *version,const char *name,const char *bugid, const char *commitid, const property_info *props, size_t numprops, const char **value)
{
return 0;
}
int prercsdiffcheckout(const struct trigger_interface_t *cb, const char *file, const char *directory, const char *oldfile, const char *newfile, const char *type, const char *options, const char *oldversion, const char *newversion, unsigned long added, unsigned long removed)
{
return 0;
}
int rcsdiffcheckout(const struct trigger_interface_t *cb, const char *file, const char *directory, const char *oldfile, const char *newfile, const char *diff, size_t difflen, const char *type, const char *options, const char *oldversion, const char *newversion, unsigned long added, unsigned long removed)
{
return 0;
}
static int init(const struct plugin_interface *plugin);
static int destroy(const struct plugin_interface *plugin);
static void *get_interface(const struct plugin_interface *plugin, unsigned interface_type, void *param);
static trigger_interface callbacks =
{
{
PLUGIN_INTERFACE_VERSION,
"Automatic checkout extension",CVSNT_PRODUCTVERSION_STRING,"CheckoutTrigger",
init,
destroy,
get_interface,
#ifdef _WIN32
win32config
#else
NULL
#endif
},
initcheckout,
closecheckout,
pretagcheckout,
verifymsgcheckout,
loginfocheckout,
historycheckout,
notifycheckout,
precommitcheckout,
postcommitcheckout,
precommandcheckout,
postcommandcheckout,
premodulecheckout,
postmodulecheckout,
get_templatecheckout,
parse_keywordcheckout,
prercsdiffcheckout,
rcsdiffcheckout
};
static int init(const struct plugin_interface *plugin)
{
return 0;
}
static int destroy(const struct plugin_interface *plugin)
{
return 0;
}
static void *get_interface(const struct plugin_interface *plugin, unsigned interface_type, void *param)
{
if(interface_type!=pitTrigger)
return NULL;
return (void*)&callbacks;
}
plugin_interface *get_plugin_interface()
{
return &callbacks.plugin;
}
#ifdef _WIN32
BOOL CALLBACK ConfigDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
char value[MAX_PATH];
int nSel;
switch(uMsg)
{
case WM_INITDIALOG:
nSel = 0;
if(!CGlobalSettings::GetGlobalValue("cvsnt","Plugins","CheckoutTrigger",value,sizeof(value)))
nSel = atoi(value);
if(!nSel)
{
EnableWindow(GetDlgItem(hWnd,IDC_CHECK2),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_CHECKOUTDEF),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_CHECKOUTMOD),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDNAME),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDOPT),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_VERBOPT),FALSE);
}
else
SendDlgItemMessage(hWnd,IDC_CHECK1,BM_SETCHECK,1,NULL);
nSel = 0;
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutVerbose",value,sizeof(value)))
nSel = atoi(value);
SendDlgItemMessage(hWnd,IDC_CHECK2,BM_SETCHECK,nSel?1:0,NULL);
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutOption",value,sizeof(value)))
SetDlgItemText(hWnd,IDC_COMMANDOPT,value);
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutCommandOption",value,sizeof(value)))
SetDlgItemText(hWnd,IDC_VERBOPT,value);
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutCommand",value,sizeof(value)))
SetDlgItemText(hWnd,IDC_COMMANDNAME,value);
else
value[0]='\0';
if(*value)
{
CheckRadioButton(hWnd,IDC_CHECKOUTDEF,IDC_CHECKOUTMOD,IDC_CHECKOUTMOD);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDOPT),TRUE);
EnableWindow(GetDlgItem(hWnd,IDC_VERBOPT),TRUE);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDNAME),TRUE);
}
else
{
CheckRadioButton(hWnd,IDC_CHECKOUTDEF,IDC_CHECKOUTMOD,IDC_CHECKOUTDEF);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDOPT),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_VERBOPT),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDNAME),FALSE);
}
return FALSE;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDC_CHECK1:
nSel=SendDlgItemMessage(hWnd,IDC_CHECK1,BM_GETCHECK,NULL,NULL);
EnableWindow(GetDlgItem(hWnd,IDC_CHECK2),nSel?TRUE:FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_CHECKOUTDEF),nSel?TRUE:FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_CHECKOUTMOD),nSel?TRUE:FALSE);
if (!nSel)
{
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDNAME),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDOPT),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_VERBOPT),FALSE);
}
return TRUE;
case IDC_CHECKOUTDEF:
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDNAME),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDOPT),FALSE);
EnableWindow(GetDlgItem(hWnd,IDC_VERBOPT),FALSE);
value[0]='\0';
SetDlgItemText(hWnd,IDC_COMMANDNAME,value);
SetDlgItemText(hWnd,IDC_COMMANDOPT,value);
SetDlgItemText(hWnd,IDC_VERBOPT,value);
return TRUE;
case IDC_CHECKOUTMOD:
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutCommand",value,sizeof(value)))
SetDlgItemText(hWnd,IDC_COMMANDNAME,value);
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutOption",value,sizeof(value)))
SetDlgItemText(hWnd,IDC_COMMANDOPT,value);
if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CheckoutCommandOption",value,sizeof(value)))
SetDlgItemText(hWnd,IDC_VERBOPT,value);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDNAME),TRUE);
EnableWindow(GetDlgItem(hWnd,IDC_COMMANDOPT),TRUE);
EnableWindow(GetDlgItem(hWnd,IDC_VERBOPT),TRUE);
return TRUE;
case IDOK:
nSel=SendDlgItemMessage(hWnd,IDC_CHECK1,BM_GETCHECK,NULL,NULL);
CGlobalSettings::SetGlobalValue("cvsnt","Plugins","CheckoutTrigger",nSel);
nSel=SendDlgItemMessage(hWnd,IDC_CHECK2,BM_GETCHECK,NULL,NULL);
CGlobalSettings::SetGlobalValue("cvsnt","PServer","CheckoutVerbose",nSel);
GetDlgItemText(hWnd,IDC_COMMANDNAME,value,sizeof(value));
CGlobalSettings::SetGlobalValue("cvsnt","PServer","CheckoutCommand",value);
GetDlgItemText(hWnd,IDC_COMMANDOPT,value,sizeof(value));
CGlobalSettings::SetGlobalValue("cvsnt","PServer","CheckoutOption",value);
GetDlgItemText(hWnd,IDC_VERBOPT,value,sizeof(value));
CGlobalSettings::SetGlobalValue("cvsnt","PServer","CheckoutCommandOption",value);
case IDCANCEL:
EndDialog(hWnd,LOWORD(wParam));
return TRUE;
}
break;
}
return FALSE;
}
int win32config(const struct plugin_interface *ui, void *wnd)
{
HWND hWnd = (HWND)wnd;
int ret = DialogBox(g_hInst, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, ConfigDlgProc);
return ret==IDOK?0:-1;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1