view kdiff3/src-QT4/ccInstHelper.cpp @ 96:9000a9763f6f

Fixed problem where destination directory would be renamed or deleted during copy operation. Now if the destination directory exists only the files inside will be copied.
author joachim99
date Thu, 25 Mar 2010 20:37:37 +0000
parents fcd146072e0c
children 0180c7f92563
line wrap: on
line source
// 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;
}
*/