You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kdiff3/src/ccInstHelper.cpp

335 lines
9.4 KiB

// 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( &param1[0] );
if ( retVal == 0 )
{
std::string param2( g_stringsize, ' ' );
retVal = popstring( &param2[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;
}
*/