|
|
|
// uninstallHelper.cpp : Defines the entry point for the console application.
|
|
|
|
//
|
|
|
|
#include <iostream>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <list>
|
|
|
|
#include <windows.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <io.h>
|
|
|
|
|
|
|
|
//#define __stdcall
|
|
|
|
|
|
|
|
#ifndef KREPLACEMENTS_H
|
|
|
|
// For compilation download the NSIS source package and modify the following
|
|
|
|
// line to point to the exdll.h-file
|
|
|
|
#include "C:/Programme/NSIS/Contrib/ExDll/exdll.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
struct ReplacementItem
|
|
|
|
{ char* fileType; char* operationType; };
|
|
|
|
|
|
|
|
ReplacementItem g_replacementTable[] = {
|
|
|
|
"text_file_delta", "xcompare",
|
|
|
|
"text_file_delta", "xmerge",
|
|
|
|
"whole_copy", "xcompare",
|
|
|
|
"whole_copy", "xmerge",
|
|
|
|
"z_text_file_delta", "xcompare",
|
|
|
|
"z_text_file_delta", "xmerge",
|
|
|
|
"z_whole_copy", "xcompare",
|
|
|
|
"z_whole_copy", "xmerge",
|
|
|
|
"_xml", "xcompare",
|
|
|
|
"_xml", "xmerge",
|
|
|
|
"_xml2", "xcompare",
|
|
|
|
"_xml2", "xmerge",
|
|
|
|
"_rftdef", "xcompare",
|
|
|
|
"_rftmap", "xcompare",
|
|
|
|
"_rftvp", "xcompare",
|
|
|
|
"_xtools", "xcompare",
|
|
|
|
0,0
|
|
|
|
};
|
|
|
|
|
|
|
|
struct LineItem
|
|
|
|
{
|
|
|
|
std::string fileType;
|
|
|
|
std::string opType;
|
|
|
|
std::string command;
|
|
|
|
std::string fileOpPart;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Return true if successful, else false
|
|
|
|
bool readAndParseMapFile( const std::string& filename, std::list<LineItem>& lineItemList )
|
|
|
|
{
|
|
|
|
// Read file
|
|
|
|
FILE* pFile = fopen( filename.c_str(), "r" );
|
|
|
|
if (pFile)
|
|
|
|
{
|
|
|
|
fseek(pFile,0,SEEK_END);
|
|
|
|
int size = ftell(pFile);
|
|
|
|
fseek(pFile,0,SEEK_SET);
|
|
|
|
std::vector<char> buf( size );
|
|
|
|
fread( &buf[0], 1, size, pFile );
|
|
|
|
fclose( pFile );
|
|
|
|
|
|
|
|
// Replace strings
|
|
|
|
int lineStartPos=0;
|
|
|
|
int wordInLine = 0;
|
|
|
|
LineItem lineItem;
|
|
|
|
for( int i=0; i<size; )
|
|
|
|
{
|
|
|
|
if( buf[i] == '\n' || buf[i] == '\r' )
|
|
|
|
{
|
|
|
|
++i;
|
|
|
|
wordInLine = 0;
|
|
|
|
lineStartPos = i;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if( buf[i] == ' ' || buf[i] == '\t' )
|
|
|
|
{
|
|
|
|
++i;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int wordStartPos = i;
|
|
|
|
if (wordInLine<2)
|
|
|
|
{
|
|
|
|
while ( i<size && !( buf[i] == ' ' || buf[i] == '\t' ) )
|
|
|
|
++i;
|
|
|
|
|
|
|
|
std::string word( &buf[wordStartPos], i-wordStartPos );
|
|
|
|
if (wordInLine==0)
|
|
|
|
lineItem.fileType = word;
|
|
|
|
else
|
|
|
|
lineItem.opType = word;
|
|
|
|
++wordInLine;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lineItem.fileOpPart = std::string( &buf[lineStartPos], i-lineStartPos );
|
|
|
|
while ( i<size && !( buf[i] == '\n' || buf[i] == '\r' ) )
|
|
|
|
++i;
|
|
|
|
|
|
|
|
std::string word( &buf[wordStartPos], i-wordStartPos );
|
|
|
|
lineItem.command = word;
|
|
|
|
lineItemList.push_back( lineItem );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool writeMapFile( const std::string& filename, const std::list<LineItem>& lineItemList )
|
|
|
|
{
|
|
|
|
FILE* pFile = fopen( filename.c_str(), "w" );
|
|
|
|
if (pFile)
|
|
|
|
{
|
|
|
|
std::list<LineItem>::const_iterator i = lineItemList.begin();
|
|
|
|
for( ; i!=lineItemList.end(); ++i )
|
|
|
|
{
|
|
|
|
const LineItem& li = *i;
|
|
|
|
fprintf( pFile, "%s%s\n", li.fileOpPart.c_str(), li.command.c_str() );
|
|
|
|
}
|
|
|
|
fclose( pFile );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string toUpper( const std::string& s )
|
|
|
|
{
|
|
|
|
std::string s2 = s;
|
|
|
|
|
|
|
|
for( unsigned int i=0; i<s.length(); ++i )
|
|
|
|
{
|
|
|
|
s2[i] = toupper( s2[i] );
|
|
|
|
}
|
|
|
|
return s2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int integrateWithClearCase( const char* subCommand, const char* kdiff3CommandPath )
|
|
|
|
{
|
|
|
|
std::string installCommand = subCommand; // "install" or "uninstall" or "existsClearCase"
|
|
|
|
std::string kdiff3Command = kdiff3CommandPath;
|
|
|
|
|
|
|
|
/*
|
|
|
|
std::wstring installCommand = subCommand; // "install" or "uninstall"
|
|
|
|
std::wstring wKDiff3Command = kdiff3CommandPath;
|
|
|
|
std::string kdiff3Command;
|
|
|
|
kdiff3Command.reserve( wKDiff3Command.length()+1 );
|
|
|
|
kdiff3Command.resize( wKDiff3Command.length() );
|
|
|
|
BOOL bUsedDefaultChar = FALSE;
|
|
|
|
int successLen = WideCharToMultiByte( CP_ACP, 0,
|
|
|
|
wKDiff3Command.c_str(), int(wKDiff3Command.length()),
|
|
|
|
&kdiff3Command[0], int(kdiff3Command.length()), 0, &bUsedDefaultChar );
|
|
|
|
|
|
|
|
if ( successLen != kdiff3Command.length() || bUsedDefaultChar )
|
|
|
|
{
|
|
|
|
std::cerr << "KDiff3 command contains characters that don't map to ansi code page.\n"
|
|
|
|
"Aborting clearcase installation.\n"
|
|
|
|
"Try to install KDiff3 in another path that doesn't require special characters.\n";
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Try to locate cleartool, the clearcase tool in the path
|
|
|
|
char buffer[1000];
|
|
|
|
char* pLastPart = 0;
|
|
|
|
int len = SearchPathA(0, "cleartool.exe", 0, sizeof(buffer)/sizeof(buffer[0]),
|
|
|
|
buffer, &pLastPart );
|
|
|
|
if ( len>0 && len+1<int(sizeof(buffer)/sizeof(buffer[0])) && pLastPart )
|
|
|
|
{
|
|
|
|
pLastPart[-1] = 0;
|
|
|
|
pLastPart = strrchr( buffer, '\\' ); // cd up (because cleartool.exe is in bin subdir)
|
|
|
|
if ( pLastPart )
|
|
|
|
pLastPart[1]=0;
|
|
|
|
|
|
|
|
std::string path( buffer );
|
|
|
|
path += "lib\\mgrs\\map";
|
|
|
|
std::string bakName = path + ".preKDiff3Install";
|
|
|
|
|
|
|
|
if ( installCommand == "existsClearCase")
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else if ( installCommand == "install")
|
|
|
|
{
|
|
|
|
std::list<LineItem> lineItemList;
|
|
|
|
bool bSuccess = readAndParseMapFile( path, lineItemList );
|
|
|
|
if ( !bSuccess )
|
|
|
|
{
|
|
|
|
std::cerr << "Error reading original map file.\n";
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create backup
|
|
|
|
if ( access( bakName.c_str(), 0 )!=0 ) // Create backup only if not exists yet
|
|
|
|
{
|
|
|
|
if ( rename( path.c_str(), bakName.c_str() ) )
|
|
|
|
{
|
|
|
|
std::cerr << "Error renaming original map file.\n";
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::list<LineItem>::iterator i = lineItemList.begin();
|
|
|
|
for( ; i!=lineItemList.end(); ++i )
|
|
|
|
{
|
|
|
|
LineItem& li = *i;
|
|
|
|
for (int j=0;;++j)
|
|
|
|
{
|
|
|
|
ReplacementItem& ri = g_replacementTable[j];
|
|
|
|
if ( ri.fileType==0 || ri.operationType==0 )
|
|
|
|
break;
|
|
|
|
if ( li.fileType == ri.fileType && li.opType == ri.operationType )
|
|
|
|
{
|
|
|
|
li.command = kdiff3Command.c_str();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bSuccess = writeMapFile( path, lineItemList );
|
|
|
|
if ( !bSuccess )
|
|
|
|
{
|
|
|
|
if ( rename( bakName.c_str(), path.c_str() ) )
|
|
|
|
std::cerr << "Error writing new map file, restoring old file also failed.\n";
|
|
|
|
else
|
|
|
|
std::cerr << "Error writing new map file, old file restored.\n";
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( installCommand == "uninstall" )
|
|
|
|
{
|
|
|
|
std::list<LineItem> lineItemList;
|
|
|
|
bool bSuccess = readAndParseMapFile( path, lineItemList );
|
|
|
|
if ( !bSuccess )
|
|
|
|
{
|
|
|
|
std::cerr << "Error reading original map file\n.";
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::list<LineItem> lineItemListBak;
|
|
|
|
bSuccess = readAndParseMapFile( bakName, lineItemListBak );
|
|
|
|
if ( !bSuccess )
|
|
|
|
{
|
|
|
|
std::cerr << "Error reading backup map file.\n";
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::list<LineItem>::iterator i = lineItemList.begin();
|
|
|
|
for( ; i!=lineItemList.end(); ++i )
|
|
|
|
{
|
|
|
|
LineItem& li = *i;
|
|
|
|
if ((int)toUpper(li.command).find("KDIFF3")>=0)
|
|
|
|
{
|
|
|
|
std::list<LineItem>::const_iterator j = lineItemListBak.begin();
|
|
|
|
for (;j!=lineItemListBak.end();++j)
|
|
|
|
{
|
|
|
|
const LineItem& bi = *j; // backup iterator
|
|
|
|
if ( li.fileType == bi.fileType && li.opType == bi.opType )
|
|
|
|
{
|
|
|
|
li.command = bi.command;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bSuccess = writeMapFile( path, lineItemList );
|
|
|
|
if ( !bSuccess )
|
|
|
|
{
|
|
|
|
std::cerr << "Error writing map file.";
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef KREPLACEMENTS_H
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
void __declspec(dllexport) nsisPlugin(HWND hwndParent, int string_size,
|
|
|
|
char *variables, stack_t **stacktop,
|
|
|
|
extra_parameters *extra)
|
|
|
|
{
|
|
|
|
//g_hwndParent=hwndParent;
|
|
|
|
|
|
|
|
EXDLL_INIT();
|
|
|
|
{
|
|
|
|
std::string param1( g_stringsize, ' ' );
|
|
|
|
int retVal = popstring( ¶m1[0] );
|
|
|
|
if ( retVal == 0 )
|
|
|
|
{
|
|
|
|
std::string param2( g_stringsize, ' ' );
|
|
|
|
retVal = popstring( ¶m2[0] );
|
|
|
|
if ( retVal == 0 )
|
|
|
|
install( param1.c_str(), param2.c_str() );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
std::cerr << "Not enough parameters." << std::endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
/*
|
|
|
|
int _tmain(int argc, _TCHAR* argv[])
|
|
|
|
{
|
|
|
|
if ( argc<3 )
|
|
|
|
{
|
|
|
|
std::cout << "This program is needed to install/uninstall KDiff3 for clearcase.\n"
|
|
|
|
"It tries to patch the map file (clearcase-subdir\\lib\\mgrs\\map)\n"
|
|
|
|
"Usage 1: ccInstHelper install pathToKdiff3.exe\n"
|
|
|
|
"Usage 2: ccInstHelper uninstall pathToKdiff3.exe\n"
|
|
|
|
"Backups of the original map files are created in the dir of the map file.\n";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return install( argv[1], argv[2] );
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
*/
|