diff

Diff3 – az „elfelejtett” csodafegyver konfigurációs fájlok frissítésére

Nem tudom Ti hogy vagytok vele, de nekem bizony majd minden napra jut valamilyen használt eszköznek a verzió frissítése. Ez legtöbbször Drupal-t jelent, de van amikor Awstats-ot, phpMyAdmin-t, valami webmail scriptet, stb …

Namármost ezeknek a programoknak közös jellemzőjük, hogy van hozzájuk egy configurációs minta fájl, amit még a telepítéskor át kell nevezni és tesre kell szabni.

Frissítéskor a testreszabott, beállított konfig fájlokat természetesen nem írjuk felül, ezek érintetlenül maradnak. Igen ám, de az eredeti alapértelmezett konfigurációs fájlok néha megváltoznak, általában egy-egy új opcióval bővülnek, vagy csak a kommenteket egészítik ki a fejlesztők.

Szóval engem mindig is zavart, hogy a régi telepítések config fájljai nem követik az új verziók frissítéseit. Annyira zavart, hogy el is kezdtem megoldást keresni. És ahogy ez lenni szokott az open source világában, hamar kiderült, hogy másokban már sokkal korábban felmerült ez a probléma, sőt már réges régen meg is oldották. A programot ami segíteni fog nekünk elhárítani ezt a problémát, úgy hívják hogy diff3. A használati útmutatója (man page) teljesen világos, én most csak a fenti esetre kihegyezve mutatom be a paraméterezését.

A diff3 használata konfig fájlok összehasonlítására

Először ellenőrizzük, hogy nincs-e ütközés a módosításokban:

diff3 -x REGI_TESTRESZABOTT REGI_DEFAULT UJ_DEFAULT

-x paraméter után három fájlnevet vár, a régi testreszabott konfig fájl, a régi eredeti konfig fájl és az új eredeti fájl. Ha üres a parancs kimenete, akkor kell örülni, akkor nincs ütközés.

A fenti három fájl segítségével hozzuk létre az új konfig fájlt, amely tartalmazza mind a mi módosításainkat, mind pedig fejlesztők módosításait.

diff3 -m REGI_TESTRESZABOTT REGI_DEFAULT UJ_DEFAULT > UJ_TESTRESZABOTT

Ha az első lépésben volt ütközés, akkor az -m kapcsoló elvégzi a migrálást.

Ezek után én még egy sima diff-el ellenőrizni szoktam, hogy minden rendben ment-e, mondjuk így:

diff -y --suppress-common-lines UJ_DEFAULT UJ_TESTRESZABOTT

A kimenetből jól látszik, hogy az új konfigurációs fájlba átvezette a diff3 a régi változtatásokat.

The Drupal way

Az imént leírtak a default.settings.php és a settings.php-re vonatkoztak. De ugyanezt a módszert szoktam használni a .htaccess fájl és a robots.txt frissen tartására is.

Persze csak kis verzió ugrásnál, pl. 7.0-ról 7.1-re, főverzió ugrásnál, pl. 6.0-ról 7.0-ra, ennél azért több munkára lesz szükség :)

Másra is használható

Természetesen másra is használható a diff3: ha egy fájlt két külön irányba módosítanak, mert mondjuk ketten dolgoznak ugyanazon a forráskódon, akkor a diff3 egyszerűen összefésüli a módosításokat. Már amennyiben nincs közvetlen ütközés a módosítások között.

Karakter alapú szöveg-összehasonlítás PHP-vel

Tartalom

Bevezető

Készülve a csütörtöki diplomavédésre, megnéztem a bíráló által feltett kérdéseket. Diplomatervem egy adatbázis séma alapú PHP kódgenerátor. (Később majd írok erről egy részletes post-ot.) A bíráló egyik kérdése volt, hogy a generált forráskód hány százalékát kell átírni egy valós környezetben.

Ez egy nagyon jó kérdés, bennem is felmerült már. Forráskód bázis rendelkezésre áll, úgyhogy van kód amin meg lehet mérni. Első ötlet lehet a diff parancs. De ebben az esetben problémás lehet, hogy a diff soronként vizsgálja a forráskódot. Ez két dolog miatt gond:

  • A generált kódban vannak felesleges blokkok, amelyeket nem töröltem hanem a // jelekkel kommenteztem ki.
  • Minden táblához létrejön egy konfigurációs fájl, amelynek az a célja, hogy testreszabáskor módosítsák. Minden sorát!

Ez a két eset nagyon gyakori, ezért a soronként összehasonlítás alapján megítélni a forráskód-generátor jóságát félrevezető lenne.

Egy karakter alapú összehasonlítás ennél sokkal pontosabb információt adna. Kicsit kutattam az interneten és találtam egy megoldást, amit kicsit átírva született a lenti kód.

Karakter alapú szöveg-összehasonlító PHP szkript

A lenti szkript definiál egy CharDiff osztályt, amit a PEAR Text_Diff csomagban található Text_MappedDiff osztályból öröklődik. A Text_MappedDiff pedig a Text_Diff-ből öröklődik, tehát a lenti osztály egyben Text_Diff osztályú is. Ez azért jó, mert a fent említett csomagban van jónéhány renderer, amelyekkel különböző szabványos patch kimeneteket lehet generálni.

De szerettem volna vizualizálni is a dolgot, ezért az osztály része egy render metódus ami HTML kimenetet ad, és grafikusan ábrázolja a a különbséget a két szöveg között.

Eredeti kód: www.hawkee.com

Íme a kód, CharDiff.php:

<?php
/**
 * Karakter alapú szövegösszehasonlító
 * -----------------------------------
 * Használat:
 * $text1 = 'árvíztűrő tükörfúrógép';
 * $text2 = 'árvíztörő tükörfúrógép';
 *
 * $diff = new CharDiff($text1, $text2);
 *
 * $diff->render();
 */

require_once 'Text/Diff.php';

class
CharDiff extends Text_MappedDiff {

  function
CharDiff ($text_src, $text_tgt) {

   
$chars_src = str_split($text_src, 1);
   
$chars_tgt = str_split($text_tgt, 1);

   
$chars_src_mapped = $chars_src;
   
$chars_tgt_mapped = $chars_tgt;

     
parent::Text_MappedDiff($chars_src, $chars_tgt, $chars_src_mapped, $chars_tgt_mapped);
  }

  function
getStat() {
   
$stat = array();

   
$stat['copy']  = 0;
   
$stat['add']  = 0;
   
$stat['del']  = 0;
   
$stat['change']  = 0;
   
$stat['change-del']  = 0;
   
$stat['change-add']  = 0;

    foreach(
$this->getDiff() as $op) {
      if (
is_a($op, 'Text_Diff_Op_copy')) $stat['copy'] += $op->norig();
      if (
is_a($op, 'Text_Diff_Op_delete')) $stat['del'] += $op->norig();
      if (
is_a($op, 'Text_Diff_Op_add')) $stat['add'] += $op->nfinal();
      if (
is_a($op, 'Text_Diff_Op_change')) { $stat['change-del'] += $op->norig(); $stat['change-add'] += $op->nfinal(); }
    }

    return
$stat;
  }

  function
render($color_delete = 'red', $color_add = 'green') {
    foreach (
$this->getDiff() as $op) {
      if (
is_a(&$op,'Text_Diff_Op_copy')) {
        echo
$this->_implode($op->final);
      }
      elseif (
is_a(&$op,'Text_Diff_Op_delete')) {
        echo
'<span style="background-color: ', $color_delete, ';">', $this->_implode($op->orig), '</span>';
      }
      elseif (
is_a(&$op,'Text_Diff_Op_add')) {
        echo
'<span style="background-color: ', $color_add.';">', $this->_implode($op->final), '</span>';
      }
      elseif (
is_a(&$op,'Text_Diff_Op_change')) {
        echo
'<span style="background-color: ', $color_delete.';">', $this->_implode($op->orig), '</span>';
        echo
'<span style="background-color: ', $color_add.';">', $this->_implode($op->final), '</span>';
      }
    }
   
    return
$return;
  }

  function
_implode($chars) {
    return
nl2br( implode('', array_map( array($this, '_htmlFilter'), $chars) ) );
  }

 
// used with array_map
 
function _htmlFilter($text) {
    return
$text = str_replace( array('&', '<', '>'), array('&amp;', '&lt;', '&gt;'), $text);
  }

}
?>

A feneti kód letölthető itt: [attachment:CharDiff.php.txt=CharDiff.php]

Az osztály használata:

<?php
  $text1
= 'árvíztűrő tükörfúrógép';
 
$text2 = 'árvíztörő tükörfúrógép';

 
$diff = new CharDiff($text1, $text2);

 
$diff->render();
?>

Remélem lesz aki hasznosnak találja majd.

Feliratkozás RSS - diff csatornájára