Comparando objetos com o WinMerge

Neste tópico vou mostrar como realizar a comparação entre duas revisões (do mesmo objeto ou de objetos diferentes) usando a ferramenta WinMerge de uma forma prática.

Primeiramente, é preciso entender que o WinMerge é uma ferramenta de comparação de texto, e portanto precisaremos ter os objetos formatados em texto plano.

Para facilitar o nosso trabalho, vamos utilizar o estado serializado do objeto que fica salvo nas Revisões do Controle de Versão do LATROMI.

Essa abordagem funcionará apenas no ambiente onde o objeto foi desenvolvido (na origem). Objetos importados de outros ambientes não poderão ser comparados pois não possuem registro de revisão.

Essa implementação será realizada usando um Extrator de Arquivos, que vai receber como parâmetro os dados dos objetos a serem comparados, gerando um arquivo .ps1. Quando este arquivo for baixado pelo usuário bastará executá-lo para fazer a comparação.

O banco de dados usado neste exemplo é o PostgreSQL.

Preparando o Ambiente

  • Certifique-se de que a extensão de arquivo .ps1 esteja liberada no IIS. Mais informações neste link.

  • Certifique-se de que o PowerShell esteja instalado no computador que vai baixar o arquivo para fazer a comparação dos objetos. O PowerShell é necessário para executar os scripts .ps1.

    Para verificar se o PowerShell está instalado, basta digitar powershell no prompt de comando:

    image

  • Execute o arquivo .bat a seguir como administrador para permitir que o PowerShell execute os scripts e para defini-lo como programa padrão para abrir os arquivos .ps1:

    @ECHO OFF
    
    REM Obtem informacoes necessarias para configuar o tipo de arquivo ".ps1"
    FOR /f "tokens=3" %%a IN ('REG QUERY "HKEY_CLASSES_ROOT\.ps1" ^|findstr /ri "REG_SZ"')                DO SET file_type=%%a
    FOR /f "tokens=3" %%a IN ('REG QUERY "HKEY_CLASSES_ROOT\%file_type%\Shell" ^|findstr /ri "REG_SZ"')   DO SET default_command=%%a
    
    REM Define o Powershell como programa padrao para abrir/executar arquivos ".ps1" 
    ECHO Confirando chave de registro
    ECHO      HKEY_CLASSES_ROOT\%file_type%\Shell\%default_command%\Command
    REG Add "HKEY_CLASSES_ROOT\%file_type%\Shell\%default_command%\Command" /ve /d "powershell \"%%1\"" /f
    
    ECHO.
    
    REM Desbloqueia a execucao de scripts nao-assinados
    ECHO Confirando politicas do Powershell
    powershell Set-ExecutionPolicy -ExecutionPolicy Unrestricted
    
    ECHO.
    ECHO Fim
    
    PAUSE
    
  • Instale o WinMerge no computador que vai fazer a comparação dos objetos.

Extrator de Arquivos

Crie um novo extrator de arquivos, e adicione os seguintes Parâmetros:

Nome Descrição
objA_UpgradeCode Código de Atualização do primeiro objeto (esq.)
objA_Revision Número da Revisão do primeiro objeto (esq.)
objB_UpgradeCode Código de Atualização do segundo (dir.)
objB_Revision Número da Revisão do segundo objeto (dir.)

Na Fonte de Dados, selecione a conexão “LATROMI” e informe o comando SQL abaixo:

WITH 
-- Retorna informações do arquivo A
file1 AS 
(
   SELECT 
      g.upgradecode,
      r.revisionid AS revision,
      format('%s-r%s.%s', g.upgradecode, r.revisionid, CASE WHEN r.objectserialization LIKE '<%' THEN 'xml' ELSE 'json' END) AS name,
      r.objectserialization AS content
   FROM wecdb.globalidmapping g
   LEFT JOIN wecdb.revisiondetails r ON r.objectglobalid = g.id AND r.revisionid = {?PARAM objA_Revision} -- Revisão
   WHERE g.upgradecode = '{?PARAM objA_UpgradeCode}' -- Código de Atualização
),
-- Retorna informações do arquivo B
file2 AS 
(
   SELECT 
      g.upgradecode,
      r.revisionid AS revision,
      format('%s-r%s.%s', g.upgradecode, r.revisionid, CASE WHEN r.objectserialization LIKE '<%' THEN 'xml' ELSE 'json' END) AS name,
      r.objectserialization AS content
   FROM wecdb.globalidmapping g
   LEFT JOIN wecdb.revisiondetails r ON r.objectglobalid = g.id AND r.revisionid = {?PARAM objB_Revision} -- Revisão
   WHERE g.upgradecode = '{?PARAM objB_UpgradeCode}' -- Código de Atualização
),
powershell AS (
   SELECT   
$$

# Modifica a codificacao para UTF-8
CHCP 65001

# Criar diretorio onde os arquivos serao extraidos
$working_directory = [System.IO.Path]::GetTempPath() + "\WinMerge Comparison\" + [guid]::NewGuid().Guid
$left_filename = "{{filename1}}"
$right_filename = "{{filename2}}"
$unpacker = "{{plugin}}"

Write-Host "Criando pastas..."

mkdir -Force $working_directory
mkdir -Force "$working_directory\Files"

Write-Host "Extraindo arquivos em $working_directory"

$left_file = @"
{{file1}}
"@

$right_file = @"
{{file2}}
"@

$project_file=@"
<?xml version="1.0" encoding="UTF-8"?>       
<project>                                    
    <paths>                                  
        <left>Files\$left_filename</left>   
        <right>Files\$right_filename</right> 
        <unpacker>$unpacker</unpacker>    
    </paths>                                 
</project>
"@

Add-Content "$working_directory\Files\$left_filename" $left_file 
Add-Content "$working_directory\Files\$right_filename" $right_file
Add-Content "$working_directory\project.WinMerge" $project_file 

Invoke-Item "$working_directory\project.WinMerge"

$$::TEXT script
)
SELECT 
   REPLACE(
      REPLACE(
         REPLACE(
            REPLACE(
                REPLACE(script, '{{filename1}}', file1.name),
                '{{filename2}}', file2.name),
            '{{plugin}}', CASE WHEN file1.name LIKE '%.xml' THEN 'PrettifyXML' ELSE 'PrettifyJSON' END),
      '{{file1}}', file1.content),
   '{{file2}}', file2.content) AS content, 
   -- Gera nome para o arquivo .bat
   CASE WHEN file1.upgradecode = file2.upgradecode THEN
      format('%s/WinMergeCompare-%s.r%s_x_r%s.ps1', TO_CHAR(CURRENT_TIMESTAMP, 'YYMMDDHH24MISS'), file1.upgradecode, file1.revision, file2.revision)
   ELSE
      format('%s/WinMergeCompare-%s.r%s_x_%s.r%s.ps1', TO_CHAR(CURRENT_TIMESTAMP, 'YYMMDDHH24MISS'), file1.upgradecode, file1.revision, file2.upgradecode, file2.revision)
   END AS filename,
   'UTF-8' AS encoding
   
FROM file1, file2, powershell

Nas Configurações, relacione as colunas da seguinte maneira:

Campo Coluna
Conteúdo do Arquivo content
Nome do Arquivo name
Codificação do Arquivo encoding

Salve e está pronto! Agora basta chamar o Extrator de Arquivos onde você precisar, como por exemplo, em uma Consulta.

Você também pode chamar diretamente pela URL do extrator de arquivos para testar:

http://site.dominio.com.br/web/downloadfile/{Codigo de Atualização do Extrator}/
     ?_objA_upgradeCode={valor}
     &_objA_revision={valor}
     &_objB_upgradeCode={valor}
     &_objB_revision={valor}

Sobre o arquivo .ps1

Se você não estiver interessado em saber o que faz o arquivo .ps1, pode pular essa etapa.

Caso tenha interesse, saiba que ele realiza as seguintes operações:

  1. Cria um diretório temporário em:
    {pasta temporário do windows}\WinMerge Comparison\{valor aleatório}

  2. Salva a serialização dos objetos (XML ou JSON) em arquivos físicos, na pasta temporária criada acima.

  3. Cria um arquivo de projeto do WinMerge (.WinMerge), com a seguinte estrutura:

    <?xml version="1.0" encoding="UTF-8"?> 
    <project> 
       <paths> 
          <left>{Caminho do arquivo 1}</left> 
          <right>{Caminho do arquivo 2}</right> 
          <unpacker>{Plugin desempacotador de XML ou JSON}</unpacker> 
       </paths> 
    </project> 
    
  4. Executa o arquivo de projeto do WinMerge criado acima.

Considerações Finais

Esta solução passou por alguma modificações até chegar ao estágio atual.

Inicialmente, era utilizado apenas um arquivo .bat, mas quando a extração envolvia arquivos muito grandes, estes arquivos acabavam sendo “cortados”.

Fora isso, a performance do PowerShell para fazer a extração dos arquivos se mostrou muito superior.

1 curtida