Archive for the ‘Developer’ Category

To localize or not to localize

Posted on May 21st, 2009 in Developer | No Comments »

Localizare în uTorrent

1 Star2 Stars3 Stars4 Stars5 Stars (3 votes, average: 3.67 out of 5)
Loading ... Loading …

Popularity: 19%

Cum ştergi exact ultima revizie dintr-un repository Subversion

Posted on May 18th, 2008 in Linux, Developer | No Comments »

Dacă ai făcut commit la ceva ce nu trebuia, sau nu la tot ce trebuia, sau pur şi simplu ai nevoie de asta din alt motiv, soluţia constă în câteva mişcări rapide. Cu magenta, am evidenţiat variabilele din comenzile de mai jos, adică ce trebuie înlocuit în funcţie de situaţia ta.

$ cp /path/to/repo /path/to/repo_backup -R

  • Am creat mai întâi un backup la structura de fişiere a repository-ului;
  • /path/to/ este calea către repository (atenţie, nu a lui working copy), iar repo este numele repository-ului; de exemplu, la mine ar putea fi /var/svn/repositories/test.

$ svnadmin dump /path/to/repo - - revision 0:n > dumpfile

  • Am făcut dump într-un fişier la toate reviziile între 0 şi n, inclusiv;
  • n este numărul reviziei dinaintea ultimei, n+1 fiind revizia curentă, la care renunţăm;
  • dumpfile este fişierul în care redirecţionăm output-ul comenzii, care altfel iese în stdout;
  • Metoda asta poate fi folosită şi pe post de backup la repository.

$ rm -rf repo

  • Am şters repository-ul, nu mai avem nevoie de el (încă avem repo_backup, dacă ceva nu merge bine de-acum înainte).

$ svnadmin create repo - - fs-type=tip

  • Am creat un repository gol, cu numele cel vechi;
  • Nu e suficient să creez doar directorul - când importăm mai târziu din dumpfile, vom primi erori dacă nu avem un repository gol;
  • Tipul repository-ului nou (bdb - sau - fsfs) trebuie să fie identic celui vechi. Înlocuieşte tip cu valoarea potrivită. Dacă nu eşti sigur care din ele este, poţi să-l afli din backup, cu comanda:

$ cat /path/to/repo_backup/db/fs-type

Trecem mai departe.

$ svnadmin load repo < dumpfile

  • Am importat conţinutul lui dumpfile, în repository-ul gol, nou creat.

În unele cazuri, mai trebuie ca owner-ul structurii de fişiere a repository-ului nou creat să fie identic cu cel al vechiului repository:

$ cd /path/to
$ ls -al | grep repo_backup
drwxr-xr-x 7 A B 4096 2008-05-18 01:28 repo_backup
$ sudo chown A:B -R repo

  • Privind iarăşi către backup-ul făcut înainte, am setat owner-ul recursiv pentru întreaga structură de fişiere a noului repository (deseori A coincide cu B);
  • În cazul meu, fluxurile SVN sunt servite de Apache (prin WebDAV), iar serverul Apache trebuie să aiba drepturi depline asupra directorului unde se află repository-ul; în cazul meu A = B = www-data (userul sub care rulează Apache sub Debian/Ubuntu). Creând acel repository la un pas anterior, owner-ul lui era utilizatorul de linux care a emis comanda .

Gata, asta e!

Un pas suplimentar, pentru cei ce folosesc un mediu Trac pentru urmărirea repository-ului SVN:

$ trac-admin /path/to/trac-environment resync

  • Am resincronizat mediul Trac (cache-ul lui intern, etc.), cu noul repository, care are mai puţin cu o revizie decât ştia Trac;
  • /path/to/trac-environment este calea către mediul Trac asociat repo-ului urmărit, de exemplu la mine ar putea fi /var/trac/test.

Note de final

Dacă doar vrei să schimbi comentariul de commit, autorul reviziei sau alte lucruri de genul ăsta, soluţia este alta - svn propset.

Working copy a rămas la revizia n+1 (dând acel commit total nefast) şi lucrurile o să-ţi cam crape în acest moment (am încercat svn cleanup şi alte variante => no use!). Soluţia este să faci un checkout nou într-un alt director şi apoi să mergi cu o unealtă specializată de tip diff (de exemplu, Araxis Merge sau WinMerge sub Windows) şi să faci un merge manual între cele două directoare. Dacă dai peste o soluţie mai buna, feel free to share it!

Ce am scris mai sus, merge de minune în linux (testat în Debian 4.0r3 cu svnadmin 1.4.2 şi trac-admin 0.10.3), în Windows nu am încercat / nu ştiu cum e. De asemenea, trebuie să ai şi drepturile potrivite pentru toate mişcările astea. Ce faci este pe riscul tău, dar dacă ai backup aşa cum am recomandat înca de la început, you should be fine.

1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 5 out of 5)
Loading ... Loading …

Popularity: 30%

Ochelarii… Inspect

Posted on May 2nd, 2008 in Developer | No Comments »

Pentru că deja s-au adunat câţiva oameni care m-au întrebat la ce îmi folosesc “ochelarii”…

Great shortcut for Firebug's Inspect tool

Este un shortcut, nu foarte cunoscut, pentru Inspect din Firebug. Poate fi adăugat din Customise [Toolbar] la right click pe orice bară de instrumente, dacă ai Firebug instalat.

Îl găsesc foarte util, aproape şi uşor de atins.

1 Star2 Stars3 Stars4 Stars5 Stars (4 votes, average: 5 out of 5)
Loading ... Loading …

Popularity: 25%

Debugging rapid în PHP

Posted on April 19th, 2008 in Developer | No Comments »

Nu o să mă întind, pentru că toată lumea a făcut deja debugging în PHP, dar o să amintesc câteva procedee care mi-au fost de mare folos, în general, în lucrul la proiecte (foarte) mari.

1. assert - Pe parcursul scriptului, în locuri în care crezi că o să crape, chemi funcţia assert dând ca parametru condiţia favorabilă. Scriptul poate fi oprit dacă valoarea de adevăr a condiţia va fi evaluată ca fiind falsă (by default, scriptul nu se opreşte). Este recomandat ca assert să fie prezent doar în timpul dezvoltării. Exemplu:

assert($expectedRows == $foundRows);

Poţi wrap-a această funcţie în myAssert, de exemplu, pentru a specifica şi alte instrucţiuni (logging etc.). Cu funcţia assert_options poţi specifica opţiuni ca:

  • ASSERT_BAIL - opreşte scriptul la evaluarea falsă a condiţiei;
  • ASSERT_QUIET_EVAL - nu sunt output-ate erori la evaluarea la fals, util dacă vrei să le loghezi pentru o depanare ulterioară;
  • ASSERT_CALLBACK - callback care se cheamă după evaluarea la fals - aici poţi face logging-ul;
  • şi altele.

2. debug_backtrace - Afişează stiva de call-uri (de funcţii) şi de include-uri care au determinat flow-ul din aplicaţie, până la momentul apelului. Întoarce un vector asociativ cu informaţii de genul: numele funcţiei, linia de cod, numele fişierului etc. şi astfel vă puteţi scrie propria metodă de afişare a acestora. Pentru rapiditate poţi folosi debug_print_backtrace (doar PHP 5), pentru un output standard. Exemplu (generat în codul WordPress-ului):

#0 include() called at [/home/designla/public_html/bogdan/blog/wp-includes/template-loader.php:20]
#1 require_once(/home/designla/public_html/bogdan/blog/wp-includes/template-loader.php) called at [/home/designla/public_html/bogdan/blog/wp-blog-header.php:21]
#2 require(/home/designla/public_html/bogdan/blog/wp-blog-header.php) called at [/home/designla/public_html/bogdan/blog/index.php:4]

Eu, de obicei, am o funcţie globală pentru aplicaţie, care conţine propria mea afişare a backtrace-ului sau care doar wrappează apelul standard de afişare.

function myBacktrace() {
debug_print_backtrace(); // Pot scrie ulterior o afisare proprie
}

3. Folosirea mecanismului de reflection. Reflection este mecanismul prin care un program îşi poate cunoaşte funcţiile, clasele şi instanţele lor, excepţii şi alte entităţi, la runtime. Eu m-am folosit foarte recent de acest mecanism, facând debugging la un proiect foarte mare şi neştiind unde era definită o funcţie pe care o apelam (în plus, existau mai multe funcţii cu acelaşi nume în aplicaţie şi o junglă de includeri până la acel apel). Simplul apel arătat mai jos, mi-a dezvăluit această informaţie. Exemplu (generat în codul WordPress-ului):

ReflectionFunction::export(’the_content); // unde the_content este numele unei functiei

Apelul a produs:

Function [ <user> function the_content ] {
@@ /home/designla/public_html/bogdan/blog/wp-includes/post-template.php 53 - 58
- Parameters [3] {
Parameter #0 [ <optional> $more_link_text = ‘(more…) ]
Parameter #1 [ <optional> $stripteaser = 0 ]
Parameter #2 [ <optional> $more_file = ” ]
}
}

Putem observa:

  • declaraţia funcţiei;
  • cine o defineşte: în cazul nostru este user defined function - <user>; strtolower, de exemplu, este <internal:standard>;
  • parametrii;
  • locaţia ei şi liniile de cod între care este cuprinsă definiţia funcţiei.

export este o metoda statică pe care o are fiecare clasă care implementează Reflector pentru entitatea respectivă, dar mai sunt şi o grămadă de metode care furnizează doar informaţiile ce te interesează.

Va urma.

1 Star2 Stars3 Stars4 Stars5 Stars (7 votes, average: 5 out of 5)
Loading ... Loading …

Popularity: 24%

Customizare prompt Bash

Posted on April 12th, 2008 in Linux, Developer | 1 Comment »

Iată o chestie marfă, cu care m-am jucat zilele trecute instalând Debian pe un sistem şi lovit de nevoia de a customiza prompt-ul de Bash - prompt-ul care totally kicks ass este cel din Gentoo, user@host cu light green si apoi calea full cu light blue şi separatorul $. Iată codul mai jos pentru asta:

export PS1=’\033[1;32m\u@\h\033[0m \033[1;34m\w\033[0m \$ ‘

Dude, WTF? Ce trebuie să ştii este că:

  • sunt mai multe secvenţe escape care înlocuiesc: user-ul (\u), numele statiei (\h), ultimul director (\W), calea lungă (\w), timpul (\t), data (\d), contoare comenzi (\# şi \!) şi altele;
  • pentru a defini formatarea, începi secvenţa de control cu \033[ şi o termini cu m - chiar aşa, gândeşte-l ca un tag de început, iar atributele se scriu cu ; între ele;
  • “atributele” permise sunt nişte coduri ce definesc (un număr limitat de) culori pentru text (e.g. 32, 34), culori pentru fundalul textului, blinking text ş.a.;
  • “tag-ul” pereche pentru încheierea definiţiei de stil are atributul 0; dacă nu închizi un tag, tot outputul viitor va fi formatat corespunzător, până shell-ul întâlneşte un bloc de reset (e.g. \033[0m);
  • PS1 vine de la Prompt Shell 1, prompt-ul principal.

Linia descrisă mai sus se introduce în ~/.bashrc -ul fiecărui user. În funcţie de distribuţia folosită poţi găsi tot felul de variaţii, uneori un stil pentru root şi altul pentru userii obişnuiţi sau mai poţi găsi secvenţele substituite cu comenzi de genul $(whoami) sau $(hostname) sau variabile gândite anterior formării string-ului; de exemplu, am văzut un prompt unde calea curentă era scurtată cu (un script folosind) puncte de suspensie atunci când era prea mare. E OK daca veniţi cu propria definiţie pentru PS1 mai târziu în fişier şi suprascrieţi precedenta, nu uitaţi să daţi export din nou. Tot în funcţie de distribuţie, definiţia pentru PS1 poate fi în altă parte (în ~/.bash_profile, pentru toţi userii în /etc/profile etc.)

Pentru testing purposes, poţi emite definiţia la care lucrezi direct în shell şi astfel va fi valabilă doar în shell-ul curent (eu cream un subshell cu su intrând din nou cu userul meu şi daca ceva nu ieşea bine, făceam exit). Dar atenţie, jucându-te în shell cu aşa ceva poate să-ţi dea bătăi de cap pentru că shell-ul nu cunoaşte numărul exact de caractere din query-ul tău şi te trezeşti cu el intercalat pe ecran (o să-ţi dai seama despre ce vorbesc) şi atunci îmbraci tag-ul cu \[ şi \] indicându-l astfel ca non-printing character, ca mai jos:

export PS1=’\[\033[1;32m\]\u@\h\[\033[0m\] \[\033[1;34m\]\w\[\033[0m\] \$ ‘ # text posibil infasurat (wrapped)!

Pentru mai multe, poţi citi în documentaţia pentru Bash (vezi capitolele 2 şi 6), conţine şi o galerie de prompt-uri (unele au mult scripting în spate), mai spre sfârşit.

Notă: E posibil ca nu toate terminalele să recunoască toate secvenţele (deci posibil niciunul), caz în care nu sunt interpretate sau sunt output-ate ca atare pe ecran (nu am testat astfel de situaţii). Ca un fapt divers, în Putty nu este activat blinking text by default.

1 Star2 Stars3 Stars4 Stars5 Stars (7 votes, average: 5 out of 5)
Loading ... Loading …

Popularity: 22%