Mjesečne arhive: December 2009

Distributed SCM, 2. dio – osnove rada sa git-om

git logo

U prošlom postu pokušao sam objasniti zašto je korištenje nekog DVCSa dobra ideja, čak i ako jedini radite na projektu, čak i ako se ne bavite programiranjem.

Kako to izgleda u praksi, vidjet ćemo uz primjere korištenja git sustava. Git je vjerojatno najpopularniji DVCS danas – koriste ga Linux kernel (za kojeg je i napisan), X.Org, GNOME i mnogi drugi projekti. Osim git-a, popularni DVCSovi danas su mercurial (hg) (Python, Mozilla, OpenSolaris) i bazaar (bzr) (Ubuntu). Iako se pojedini pojmovi i način rada pomalo razlikuju od sustava do sustava, osnovna ideja je ista.

Za primjer projekta uzet ćemo Hello World program u C-u pod Linuxom. Osim samog programa (hello.c datoteka), projekt će sadržavati i Makefile datoteku za buildanje programa te README.txt sa uputama za program.

Inicijalizacija repozitorija

Kako tek započinjemo s projektom, kreirat ćemo novi prazni direktorij hello i u njemu inicijalizirati prazan git repozitorij (u mom primjeru, projektni direktorij kreirao sam u home (~) direktoriju):

> mkdir hello
> cd hello
> git init
Initialized empty Git repository in ~/hello/.git/

Git sve svoje podatke sprema u poddirektorij .git vašeg projekta. Za razliku od SVN-a, koristi se samo jedan za cijeli projekt, a ne po jedan za svaki direktorij unutar vašeg projekta.

Ukoliko ste već prije započeli rad na projektu, a želite početi koristiti git na njemu, možete pokrenuti git init izravno u direktoriju projekta. Ukoliko želite raditi sa repozitorijem nekog projekta koji već koristi git, originalni repozitorij možete klonirati i onda raditi na svom klonu. Primjer za Empathy (GNOME chat client):

> cd /tmp
> git clone git://git.collabora.co.uk/git/empathy.git
Initialized empty Git repository in /tmp/empathy/.git/
....

Committanje

Jednom kad ste inicijalizirali projekt (na bilo koji način), možete raditi promjene i spremati ih. Kreirajmo datoteku hello.c i u nju spremimo prvu verziju našeg Hello World programa:

void main() { printf("Hello world\n"); }

Brza provjera pokazuje da se stvar kompajlira uz neka upozorenja. Za početak smo zadovoljni pa želimo spremiti prvu verziju. Da bi to napravili, gitu moramo reći da mora voditi računa o datoteci hello.c te da smo je upravo promijenili:

> git add hello.c

Napomena: ovaj add ne znači da smo datoteku dodali u repozitorij, nego smo datoteku označili za spremanje u slijedećem commitu. Pošto datoteka još nije bila spremana u repozitoriju, prilikom commita će biti stvorena. Napravimo commit sa komentarom “prva verzija” (ukoliko ne dodate komentar u komandnoj liniji, otvorit će vam se editor pa se možete raspisati do mile volje):

> git commit -m "prva verzija"
[master (root-commit) ac3a485] prva verzija
 1 files changed, 2 insertions(+), 0 deletions(-)
 create mode 100644 hello.c

Git nam govori da je spremio prvi commit u master granu (branch). Master grana uvijek postoji u git repozitoriju (osim ako radite čudne stvari :) te se automatski stvara kod inicijalizacije novog repozitorija ili kloniranja postojećeg, te je po defaultu aktivna.

Pogledajmo što zasad sve imamo spremljeno u master grani:

> git log
commit ac3a48559de3b7f225ffa96c504a8586057fb4b9
Author: Senko Rasic <senko@localhost>
Date:   Fri Dec 11 00:38:16 2009 +0100
prva verzija

Ovaj čudan niz znakova u prvoj liniji je jedinstveni ID commita. Kada želite pregledavati pojedine committove, vraćati se natrag u prošlost, preuzimati committove iz jedne grane u drugi i slično, obično trebate koristiti ovaj ID. Ne brinite, ne trebate ga ručno utipkavati cijelog – git je dovoljno pametan da ga prepozna iz prvih par znakova (bar 4, ali ukoliko ima više committova koji počinju sa istim znakovima, onda možete specificirati i više znakova). Pogledajmo detalje ovog što smo upravo spremili:

> git show ac3a
commit ac3a48559de3b7f225ffa96c504a8586057fb4b9
Author: Senko Rasic <senko@localhost>
Date:   Fri Dec 11 00:38:16 2009 +0100

prva verzija

diff --git a/hello.c b/hello.c
new file mode 100644
index 0000000..d08059a
--- /dev/null
+++ b/hello.c
@@ -0,0 +1,2 @@
+void main() { printf("Hello world\n"); }
+

Commit se sastoji od jedinstvenog ID-a, različitih polja (najčešća su Author i Date, ali može ih biti još), poruke koja opisuje što se napravilo (može biti jedan ili više redova), te same promjene u diff formatu. U ovom slučaju kreirali smo novu datoteku pa u diffu piše da je prethodna verzija bila /dev/null :)

Da biste pogledali zadnji commit, ne morate navoditi njegov ID. Tako smo istu stvar mogli napraviti i samo pozivanjem git show.

Work tree, staging area

Krenimo dalje sa našim projektom. Prva verzija datoteke nije baš reprezentativni C kod, pa ćemo je malo uljepšati. Editirajmo hello.c da izgleda ovako:

void main(void)
{
  printf ("Hello world\n");
}

U ovom trenutku u našem radnom direktoriju (work tree) postoje promjene koje još nismo pospremili. Nepospremljene promjene možemo vidjeti u diff formatu:

> git diff
diff --git a/hello.c b/hello.c
index d08059a..145804e 100644
--- a/hello.c
+++ b/hello.c
@@ -1,2 +1,4 @@
-void main() { printf("Hello world\n"); }
-
+void main(void)
+{
+  printf ("Hello world\n");
+}

Ukoliko je promjenjeno više datoteka, razlike za pojedinu datoteku (ili pojedini direktorij) možemo vidjeti navodeći njeno ime: git diff hello.c. Primjetite da će git diff pokazati promjene samo u datotekama koje prati, odnosno one za koje ste mu rekli da su dio repozitorija. Čim datoteku jednom označite sa git add, git će je pratiti (sve dok je ne obrišete sa git rm). Pregled stanja radnog direktorija, s popisom promjenjenih praćenih(tracked) i popisom nepraćenih (untracked) datoteka možemo vidjeti sa git status.

Označimo datoteku za spremanje:

> git add hello.c
> git diff
> git diff --cached
diff --git a/hello.c b/hello.c
index d08059a..145804e 100644
--- a/hello.c
+++ b/hello.c
@@ -1,2 +1,4 @@
-void main() { printf("Hello world\n"); }
-
+void main(void)
+{
+  printf ("Hello world\n");
+}

Nakon označivanja za spremanje, git diff više ne prijavljuje nikakve razlike! To je zbog toga što su razlike sada u pripremi za commit (staging area). Pripremljene razlike možemo vidjeti sa git diff --cached. Ukoliko smo nešto zeznuli pa ne želimo napraviti commit nad njima, git reset miče promjene nazad iz staging area i možemo ih nakadno opet označiti za spremanje. Napomena: git reset, ukoliko dodate još neke parametre (npr. –hard koji briše promjene i iz radnog direktorija, ili id committa, koji vas “vraća” na taj commit i briše sve naknadne promjene), može biti vrlo opasna po vaše podatke. Prilikom eksperimentiranja svakako pročitajte manual za git-reset.

Ukoliko samo želite označiti sve promjenjene datoteke (koje su dodane u repozitorij, tj. git ih prati) i napraviti commit svih njih, to možete učiniti ovako:

> git commit -a -m "malo uljepsano"
git commit -a -m "malo uljepsano"
[master 459b8bd] malo uljepsano
 1 files changed, 4 insertions(+), 2 deletions(-)

Uz ove osnove možete već početi raditi sa repozitorijom, spremati i pregledavati svoje promjene, ali zasad se git ne čini previše različitim od CVS-a ili SVN-a. U slijedećem postu bacit ćemo se na zanimljivije stvari – branching, merging, rebasing. Stay tuned :)

Distributed Source Code Management, 1. dio – što, kako i zašto

Bavite li se programiranjem, dizajnom ili nekim drugim kreativnim radom na računalu?

DVCS For The Win

tree

Ukoliko je odgovor da, vjerojatno koristite neki sustav za rukovanje različitim verzijama vašeg uratka, pa makar to bili to direktoriji nazvani “novo”, “novije-2″, “staro-prošli-tjedan”. Moguće je da već i koristite neke od mnogobrojnih VCS / SCM sustava; no, podržava li sustav koji koristite i distibuiran rad?

Čak i ako sami radite na projektu i nitko nikada neće vidjeti ništa osim finalnog proizvoda, isplati se koristiti distribuirani sustav za verzioniranje projekta (DVCS – Distributed Version Control System) — osim jednostavnosti zbog toga što nije potrebno konfigurirati i spajati se na centralni repozitorij (čak i ako on bio na vašem lokalnom disku), DVCS-ovi vam pružaju nešto mnogo više, a to je puno, puno veća sloboda u eksperimentiranju na vašem projektu.

A kod kreativnog rada gdje možete imati mnogo draftova koje kombinirate, bacate u zaborav, vučete nazad iz ladice, slažete jedne preko drugih i na kraju dobijate konačan proizvod, ta sloboda u eksperimentiranju je ključna.

Što ne valja kod klasičnih sustava…

Kod klasičnih sustava (u koje spada i “kreiram-backup-direktorije-svako-malo” ad-hoc pristup), princip čuvanja verzija je linearan. Imate neku početnu verziju vašeg uratka, napravite promjene na njoj i kad ste zadovoljni pospremite novu verziju negdje na sigurno (npr. commit na server ili novi backup dir). Ukoliko kasnije saznate da ste nešto zeznuli, uvijek se možete vratiti na raniju spremljenu verziju, odnosno imate beskonačni undo.

Ali, jednom kada se vratite u prošlost (odlučite da novija verzija ne valja) i krenete drugim smjerom (kreirate novu granu projekta), praktički ste prisiljeni baciiti sve načinjene promjene u smeće, čak i ako dio njih još uvijek ima smisla. U teoriji vi možete iz zadnje verzije izvući dio promjena koji želite sačuvati i onda to primjeniti na novu granu. U praksi, svatko tko je radio netrivijalne SVN mergeove ili ručno kopirao izrezani dizajn i onda prepravljao da paše po drugom layoutu zna da to nije nimalo zabavan posao. U praksi, vi ručno morate napraviti posao koji bi VCS trebao moći napraviti za vas.

Zbog toga, najčeće se commitovi rade jednom kad ste prilično sigurni da je stvar ono što bi htjeli da bude. Rezultat toga je da se commit više koristi kao checkpoint, tj. pamti se trenutak u kojem je draft u “dobrom stanju”. Odnosno, promjene imeđu commitova su velike i često uključuju detalje koji nemaju nužno veze jedni s drugim, ali ste ih mijenjali u istom vremenskom periodu pa su eto završili zajedno.

… i kako distribuirani sustavi to popravljaju

Za razliku od toga, DVCS-ovi počinju od pretpostavke da postoji puno različitih grana u kojima se projekt neovisno razvija (jedan developer ima bar po jednu granu na kojoj on ili ona radi). Zbog toga si DVCS-ovi daju mnogo truda da osiguraju da se promjene jednog developera mogu jednostavno i sigurno kombinirati sa promjenama drugih, odnosno da se različite grane projekta mogu na siguran način mergeati.

Kako bi to osigurali, DVCS-ovi traže što manje promjene iz commita u commit, jer su male promjene puno manje ovisne o globalnom stanju u kojem je vaš projekt – ovise samo o nekoliko “susjednih” stvari (npr. nekoliko linija ispred i iza promjene u programskom kodu). Na taj način i developere “tjeraju” da promjene spremaju što ćešće i da međusobno neovisne promjene spremaju u različitim committovima.

Isto vrijedi i za vas kao solo developera na projektu. Filozofija DVCS-a je da za svaku ideju u projektu imate po jednu granu, u kojoj onda promjene nižete u puno commitova od kojih svaki sadrži malu promjenu. Ukoliko imate nekoliko stvari (ili alternativa iste stvari) na kojima radite u isto vrijeme, imat ćete nekoliko grana u repozitoriju. Ukoliko se tijekom razvoja pokaže da bi vam u jednoj grani dobro došle promjene koje ste već napravili za drugu granu, jednostavno “povučete” dotične commitove i automatski primjenite njihove promjene.

Odnosno, kod DVCS-ova grane projekta (branches) preuzimaju ulogu koju kod klasičnih VCS-ova imaju committovi. DVCS-ovi comittovi su, pak, dovoljno mali da ih je puno lakše preslagivati i kombinirati — ukoliko i dođe do konfliktalakše je izolirati problem i popraviti ga.

Kako organizirati repozitorij

Ukoliko ste novi u korištenju DVCS-a (ili čak klasičnih VCS-ova), sve ovo vam vjerojatno zvuči prilično zakomplicirano. Evo nekoliko općenitih savjeta kako jednostavno organizirati repozitorij za solo rad:

Za trenutni “dobar” draft (stanje s kojim ste zadovoljni i koje dalje nadograđujete – ono što biste zadnje skopirali u backup direktorij da sve to radite ručno) obično se koristi zasebna grana zvana master. Master je dakle početna točka za promjene koje radite.

Za svaku ideju, dodatak funkcionalnosti, bugfix, alternativu …., koju planirate, otvorite novu granu u kojoj ćete raditi samo na tome. Grana se kreira “grananjem” od mastera. Nakon što napravite par promjena u grani, ona će imati nekoliko comittova više od mastera (tj. sve comittove od prije + par novih koje ste napravili).

Kad ste zadovoljni sa promjenama koje ste napravili (npr. napisali ste i istestirali bugfix za vaš kod), granu spajate nazad u master, tj radite merge. Sustav će to napraviti tako da će uzeti sve comittove koji postoje u vašoj grani i redom ih zalijepiti na master. Ukoliko dođe do konflikta, trebat ćete popraviti samo zeznuti commit.

Da biste minimizirali mogućnost konflikta, trebate samo paziti na nekoliko stvari: da pojedini committovi budu što manji (i stoga što manje ovisini o ostatku koda), da pojedine grane ne rade promjene na istom mjestu (odnosno, ako rade, da koriste isti commit a ne zasebne committove za istu stvar) te da razlika između pojedine grane i mastera bude što manja.

Ovo zadnje zvuči kontra-produktivno – koji je smisao grane ako se ne smije (mnogo) razlikovati od mastera? Ne brinite, dugovječne i velike grane su sasvim česta pojava. Nema nikakve opasnosti da grana ima mnoge committove kojih nema u masteru – kod mergea će se oni samo zalijepiti na mastera i gotovo. Problematični dio su committovi kojih ima u masteru, a nema u dotičnoj grani – ova situacija događa se kad imate više grana pa jednu mergeate u master – ostale grane nemaju committove koje je ta grana sadržavala.

Stoga, da bi se smanjila mogućnost konflikta, ili bar olakšalo njegovo rješavanje, u dugovječnim granama treba s vremena na vrijeme povući u granu nove committove koji su došli u master. To se obično naziva rebase, a radi se tako da se privremeno maknu svi committovi iz grane, povuku se nove stvari iz mastera, a na kraju se committovi iz grane vraćaju jedan po jedan. Na taj način dobija se efekt kao da je grana kreirana iz trenutnog mastera.

Napomena: terminologija i organizacija razlikuju se ponešto od sustava do sustava; npr. neki nemaju više grana u jednom repozitoriju nego je svaka grana repozitorij za sebe. Ali osnovna ideja i način rada isti je za bilo koji od DVCS-ova.

Za kraj, najava

Ako ste nakon svega ovog pomalo (ili malo više od malo) zbunjeni, ne brinite. Stvar u praksi nije toliko komplicirana kako se čini (a moguće da sam je i ja komplicirano objasnio, primam sugestije u komentarima :). Stoga ne propustite slijedeći post u kojemu ću proći kroz osnove korištenja DVCSa koristeći kao primjer git, vjerojatno najpopularniji distribuirani VCS.

git_branch_madness
kako to izgleda kad zakomplicirate stvari ;-)

DIY: napravite vlastiti Firefox OS u 3 koraka

firefox-os

Ukoliko ste u zadnje vrijeme pratili IT vijesti, vjerojatno ste već čuli za Google Chrome OS koji je baziran na Linux jezgri i Google Chrome web pregledniku. Ovaj operacijski sustav namjenjen je uporabi samo web aplikacija – niti podaci niti programi se ne instaliraju na računalo.

(Gotovo) cijeli Chrome OS je, kao i sam Chrome open source (po standardnoj Googleovoj “open source” filozofiji: napravi nešto interno i izbaci kod van). Zbog toga je razmjerno jednostavno napraviti vlastitu verziju (npr. sa nekim izmjenama i dopunama) koristeći originalni izvornik kod dustupan u sklopu Chromium OS projekta.

Ali mi ćemo ovdje krenuti drugim smjerom – koliko je teško složiti OS poput Chromea počevši od obične Linux distribucije, sa Firefoxom kao browserom? Vrlo jednostavno! Evo kako:

1. Kreirajte i skinite personaliziranu Slax distribuciju

Distribucija Slax je idealna za ovu priliku. Slax je vrlo mala distribucija koja je istovremeno i Live CD/USB i installer. Još bolje, odmah na web stranicama moguće je uz par klikova odrediti što točno želite uključiti u distribuciju.

Za naš OS, trebat će nam Linux baza (Core), X sučelje (Xorg) i Firefox. Krenite na Build Slax stranicu i isključite višak paketa. (Na popisu spremnih modula je i Opera pa ukliko ste Opera korisnik možete Firefox OS pretvoriti u Opera OS).

Nakon odabira koponenti, preuzmite TAR verziju Slaxa.

2. Modificirajte Live CD/USB da odmah pokreće Firefox

Raspakiravanjem TAR verzije dobit ćete boot direktorij koji sadrži alate za podizanje sustava te slax direktorij koji sadrži osnovni sustav, zapakirane module tzv. rootcopy direktorij koji služi za customizaciju Slaxa. Što god stavite u ovaj direktorij, bit će kopirano na sustav kad se podigne sustav.

Da bi po pokretanju grafičkog sučelja odmah bio pokrenut i Firefox i to u full-screenu, potrebno je kreirati direktorij slax/rootcopy/root i u njemu datoteku .xinitrc koja će specificirati pokretanje Firefoxa umjesto normalnog grafičkog sučelja:

  > cd slax/rootcopy
  > mkdir root
  > echo "/usr/bin/firefox" > root/.xinitrc

Osim ovog, trebamo još maknuti boot izbornik koji se kod Slaxa po defaultu pojavljuje i čeka na korisnikov odabir. Nas zanima samo izravno pokretanje sustava. Konfiguracija za bootloader nalazi se u boot/slax.cfg datoteci. Umjesto cijelog sadržaja datoteke (koji prikazuju grafički boot izbornik) potrebna nam je samo jedna linija (napomena: ovo ide u jednu liniju iako je to ovdje razlomljeno u dvije):

  DEFAULT /boot/vmlinuz initrd=/boot/initrd.gz ramdisk_size=6666
      root=/dev/ram0 rw autoexec=xconf;telinit~4 changes=/slax/ nohd

Ovo je zapravo prepisana linija iz originalnog slax.cfg koja pokreće grafičko sučelje uz dodatak nohd opcije koja osigurava da sustav neće pokušati pristupiti hard diskovima u računalu.

Da bi stvar natrag zapakirali u Live CD koristite priloženu slax/make_iso.sh skriptu koja će kreirati ISO image za CD. Za kreiranje Live USB-a koristite skriptu boot/bootinst.sh koja radi instalaciju izravno na stick. Oprez: pazite da prilikom pokretanja bootinst.sh kao uređaj ne navedete vaš disk, jer skripta modificira MBR i može vam zeznuti sustav.

3. Konfigurirajte Firefox i uključite ekstenzije po želji

Isprobajte netom napravljenu instalaciju, na pravom ili virtualnom računalu. Ja sam koristio ISO image i stvar isprobavao u KVM/QEMU virtualnom računalu, no ako preferirate VMWare ili VirtualBox, stvar je analogna. Računalo (virtualno ili stvarno) trebalo bi imati bar 512 MB memorije kako bi Firefox mogao nesmetano raditi.

Ukoliko je sve prošlo kako treba, Firefox bi se trebao podignuti odmah po startu. Kao dodatni bonus, Firefox na Slaxu po defaultu dolazi sa Chrome-like temom :-)

Slijedeći korak je konfiguracija Firefoxa i instalacija add-onova na standardni način. U svom testiranju ja sam instalirao AdBlock+ i Adobe Flash. Flash instalacija nije automatska, nego je potrebno preuzeti arhivu u tar.gz formatu, raspakirati je, a dobivenu libflashplayer.so datoteku prekopirati u plugins direktorij:

  > cd /root/Downloads
  > tar xzf install_flash_player_10_linux.tar.gz
  > mkdir /root/.mozilla/plugins
  > cp libflashplayer.so /root/.mozilla/plugins

Restartom Firefoxa Flash plugin bi trebao biti aktivan.

Kako se sve radi u ramdisku, sve napravljene promjene će biti izbrisane po gašenju računala. Da bi sačuvali Firefox konfiguraciju, cijeli /root/.mozilla/ direktorij (sa vašeg novog Firefox OS sustava) treba skopirati u slax/rootcopy/root/.mozilla/ direktorij na sustavu gdje slažete instalaciju.

Gotov proizvod: samo vaš Slax Firefox OS!

Nakon što još jednom generirate installer (da uključi i Firefox konfiguraciju), vaš novi OS je spreman! Ukoliko ga zapržite na CD ili postavite na USB stick, možete ga uvijek nositi sa sobom i koristiti na bilo kojem računalu koje možete bootati :)

Ako želite isprobati kako stvar radi, a ne želite se mučiti sa opisanim koracima, konačni rezultat u obliku DVD ISO imagea možete preuzeti ovdje: Slax Firefox OS (ISO, 117 MB). Ukoliko stvar želite testirati na virtualnom računalu, ne trebate pržiti CD, samo vašem omiljenom programu (VMWare, VirtualBox, qemu ili što već) kažite da za virtualni CD koristi priloženi image (a možete ga i “mountati” koristeći DaemonTools pod windowsima ili losetup pod Linuxom).

Jedna napomena uz wireless: Slax bez problema pronalazi i konfigura žičanu mrežu putem DHCP-a. Kako sam cijelu stvar isprobavao u virtulanom računalu, nije mi trebala wireless podrška, stoga ne znam kakva je wireless podrška po defaultu u Slaxu. Dodatnu/alternativnu podršku pružaju dodatni moduli koje je moguće uključiti u vaš Slax sustav pa taj dio ostavljam kao vježbu za čitatelja :)

Osim toga, u daljnjem razvoju bi bilo zgodno kreirati običnog korisnika i složiti pokretanje Firefoxa pod njim (umjesto pod root accountom kako je po defaultu) kako čak i u slučaju kompromitacije Firefoxa ne bi postojala nikakva mogućnost da napadač u otvorenom remote shellu pokuša pristupiti lokalnim diskovima. Naposlijetku, bilo bi zgodno izbaciti sve ostale stvari iz Slax Core i ubrzati boot proceduru za još nekoliko sekundi. Ovo također ostavljam kao vježbu za čitatelja :)

Dohvaćanje i prikaz Twitter lista pomoću PHP-a

Jučer su vam pokazali kako na jednostavan i efektan način na stranicu dodati listu prijatelja.

Inspiriran njihovim uratkom i nedavnom Twitter novotarijom – listama, složio sam malu skriptu koja omogućuje dohvaćanje popisa Twitter korisnika sa neke liste (ili popis svih listi nekog Twitter korisnika) i jednostavno ubacivanje u postojeću stranicu.

Prvo demonstracija; kliknite ovdje kako bi vidjeli popis Twitter lista by Nikola (ja sam zasad prelijen složiti svoje liste pa koristim tuđe :), a nakon toga i ljude na njegovoj listi za odstrel.

Kod za to izgleda otprilike ovako:

<?
  # Učitamo pomoćne funkcije za dohvaćanje lista
  require('twitter-lists.php'); ?>

  # Podesimo parametre za pristup Twitter API-u
  $twitter_username = 'vas_twitter_username';
  $twitter_password = 'vas_twitter_password';

  # Zatražimo popis svih Nikolinih lista
  $liste = twitter_get_lists('nikolaplejic');

  # Zatražimo popis ljudi na linux-people listi
  $linuxasi = twitter_get_list_members('nikolaplejic', 'linux-people');

  # Ispišemo jednostavnu UL sa popisom lista
  display_twitter_lists($liste, 'css-class-za-ul');

  # Analogno za popis ljudi u linux-people
  display_twitter_lists($linuxasi, 'css-class-za-ul');

  # Isti popis, ali uz korištenje IMGova za avatare ljudi
  display_twitter_lists($linuxasi, 'css-class-za-ul', true);

Kod za dobavljanje i ispis lista možete pogledati i skinuti odavde. Podaci sa Twittera se pamte 1 sat, što znači da koliko god da vam stranica bude posjećena nećete preći Twitter limit. Ukoliko Twitter servis nije dostupan (zna se dogoditi :), neće doći do greške nego će dobivene liste biti prazne.

CSS spriteovi se ne koriste jer bi ih trebalo ručno generirati što pobija cijelu poantu ovog koda, a automatsko generiranje (iako moguće) bilo bi overkill i presporo i svakako bi bilo tema za neki drugi put.

Kod bi trebao dobro raditi na bilo kojoj novijoj instalaciji PHP-a (specifično, instalacija biti PHP 5.2.0 ili viši i imati uključenu JSON podršku i podršku za otvaranje URLova kao datoteka)

Ukoliko vam se kod čini koristan, slobodno ga koristite na bilo koji način. Još jednom hvala braći Blagonić na njihovom tutorialu, kako zbog korisnosti tako i zbog inspiracije za ovaj post :)