Sayfalar

18 Şubat 2011 Cuma

Çomak ve Bonobo Hakkında

    Bildiğiniz üzere bu hafta içinde Pazartesi günü benimde içinde bulunduğum Çomak ekibi ilk meyvesini verdi ve Kde'den bağımsız bir Pardus sürümü olan Bonobo'yu, Lxde masaüstü ortamıyla birlikte yayınladı. Daha ilk günden çok sayıda kişi tarafından indirilen Bonobo genel olarak iyi tepkilerle karşılandı. Tabii ki eksikleri, hataları var ve biz de ekip olarak kullanıcılar tarafından bize ulaştırılan geri bildirimlerle farkettiğimiz hataları çözerek Bonobo'yu daha hatasız bir hale getirmeye çalışıyoruz. Hataların bize bildirilmesi için proje kapsamında kullandığımız liste ve blog(yorum yazarak) kullanılabilir. Bu yönde ilk güncelleme ve hata çözümü kısa zamanda yayınlandı.
   
    Bu süreç içinde neler yaptığımızdan bahsetmek gerekirse öncelikle iki grup halinde çalıştığımızı söyleyebilirim. Bir grup Kde kütüphanelerini kullanan Pardus yöneticilerini mümkün olduğunca saf Qt kullanacak ve Kde'ye ihtiyaç duymadan çalışacak şekilde düzenlerken diğer grup da masaüstü ortamlarının eksik pprogramlarının paketlenmesi ve çalışan bir sistem elde etmek üzere çalışmaktayız.
   
    Pardus yöneticilerinin nasıl Kde bağımsız hale getirildiği hakkında daha ayrıntılı bilgiyi bu konuda çalışan arkadaşların (Aydan, Merve, Gökhan, Orçun, Tayfur, Kaan, Sertaç) ve projenin bloğundan ayrıca daha teknik konuların da konuşulduğu projenin listesinden takip edebilirsiniz.
   
    Öte yandan yöneticilerin çalışabileceği masaüstü ortamlarının çalışılabilir hale getirilmesi ve eksik programların paketlenmesi çalışmaları devam etti. Gerekli paketler güncellendi. Bazı programlar(pcmanfm) svn,git sürümlerindeki son hallerine güncellendi. Sanal makinalar üzerinden yaptığımız denemeler sonucu arada, yine sanal makinalarda kullanılabilecek .ova dosyaları yayınlandı. Blogda da bahsedilen LXDM'nin otomatik başlamaması gibi sorunlar halledildi.
   
    Bir diğer adım olarak Enlightenment için de çalışmalarımız hızla devam etmekte. Depodaki Enlightenment paketlerinin dışında bir çok yeni Enlightenment bileşeni ve programı paketlendi. Şimdilik çözmemiz gereken bazı sistem programlarının otomatik çalıştırılması, Pardus'a özel ayarların düzenlenmesi(arkaplan vs), dosya ilişkilendirilmelerinin ayarlanması vb. gibi işlerimiz var. 
  
    Birkaç gün içinde (büyük ihtimalle) bu işleri de halledip Bonobo'dan sonra Enlightenment'la çalışan bir Pardus sürümü yayınlayacağız.

10 Ocak 2011 Pazartesi

Pardus Konsolda Müzik Dinlemek

MPD, servis (daemon) olarak sistem arkaplanında çalışan, aynı zamanda masaüstü yöneticisinden ve oturumlardan bağımsız olarak çalışan bir müzik çalma servisidir. Açılımı, Music Player Daemon'dur. Pulseaudio desteği vardır ve son derece hafiftir. İnternet üzerinden müzik yayını yapmanıza izin verir. İnternette çeşitli konfigürasyon ayarlarını bulabilirsiniz.

Paket deposundan kurmak için:
$ sudo pisi it mpd mpc


Kurduktan sonra servisi çalıştırmak için:
# service mpd start

Daha sonra, root olarak /etc/mpd.conf dosyasındaki aşağıdaki satırı kendi müzik dizininize göre değiştirin:

...        
music_directory                 "/mnt/archive/music"
...



Daha sonra aşağıdaki komutla veritabanını güncelliyoruz:
$ mpc update


Şimdi de ncmpcpp istemcisini kuralım:
$ sudo pisi it ncmpcpp


İstemcimizi de kurduğumuza göre konsolda ncmpcpp komutuyla istemciyi çalıştırıyoruz. 1-9 tuşlarıyla ya da (F1-F9) ncmpcpp görünümleri/tabları arasında geçiş yapabilirsiniz. Önce 1(F1) tuşuyla kısayollara göz atsanız iyi olur. İyi dinlemeler.


Kaynak: http://tr.pardus-wiki.org/MPD

7 Ocak 2011 Cuma

Python ConfigParser (Configuration file parser) Modülü

Bu modül ConfigParser sınıfını tanımlar. ConfigParser sınıfı Microsoft Windows INI dosyalarında bulabileceğinize benzer yapıda basit ayar dosyası ayrıştırma(parser) dili gerçekleştiri. Bunu son kullanıcılar tarafında kolaylıkla özelleştirilebilecek Python programları yazmak için kullanabilirsiniz.

Ayar dosyası [section] başlığıyla sağlanan bölümler ve onu takip eden isim: değer girdileri içerir; isim=değer şeklinde de kullanılabilir. Aradaki boşluklar gözardı edilecektir. '#' ya da ';' ile başlayan satırlar gözardı edilir ve yorum için kullanılabilir.


Yorumlar kendi başlarına boş bir satırda veya değerlerin ya da bölüm isimlerinin bulunduğu satırlarda bulunabilir. İkinci durumda yorum olduklarının anlaşılabilmesi için arada(yorumdan önce) boşluk bulunması gerekir. (Geriye uyumluluk için sadece ; satır içi yorum başlatır.)

Seçimli(optional) değerler aynı ya da özel bir DEFAULT bölümdeki başka değerlere işaret eden format stringleri içerebilirler.

Örneğin:

[Section]
foodir: %(dir)s/whatever
dir=frob
long: this value continues
   in the next line


burada %(dir)s dir 'in değerine sahip olacaktır(örnek için flob). Bütün referans genişletmeleri gerektiğinde gerçekleştrilir.

Öntanımlı(default) değerler ConfigParser yapıcısına sözlük tipinde bir parametre olarak verilebilir. Ek öntanımlılar diğer değerleri geçersiz kılacak get() metoduna verilebilir.Bölümler normalde dahili sözlükte saklanırlar. Alternatif bir sözlük ConfigParser yapıcısına parametre olarak verilebilir.

Örnekler:
Bir ayar dosyasına yazma örneği:

import ConfigParser

config = ConfigParser.RawConfigParser()

# When adding sections or items, add them in the reverse order of
# how you want them to be displayed in the actual file.
# In addition, please note that using RawConfigParser's and the raw
# mode of ConfigParser's respective set functions, you can assign
# non-string values to keys internally, but will receive an error
# when attempting to write to a file or when you get it in non-raw
# mode. SafeConfigParser does not allow such assignments to take place.
config.add_section('Section1')
config.set('Section1', 'int', '15')
config.set('Section1', 'bool', 'true')
config.set('Section1', 'float', '3.1415')
config.set('Section1', 'baz', 'fun')
config.set('Section1', 'bar', 'Python')
config.set('Section1', 'foo', '%(bar)s is %(baz)s!')

# Writing our configuration file to 'example.cfg'
with open('example.cfg', 'wb') as configfile:
    config.write(configfile)

Bir ayar dosyası okuma örneği:


import ConfigParser

config = ConfigParser.RawConfigParser()
config.read('example.cfg')

# getfloat() raises an exception if the value is not a float
# getint() and getboolean() also do this for their respective types
float = config.getfloat('Section1', 'float')
int = config.getint('Section1', 'int')
print float + int

# Notice that the next output does not interpolate '%(bar)s' or '%(baz)s'.
# This is because we are using a RawConfigParser().
if config.getboolean('Section1', 'bool'):
    print config.get('Section1', 'foo')


Ayrıntılı belgelendirme ve daha fazla örnek için:http://docs.python.org/library/configparser.html

29 Aralık 2010 Çarşamba

Crontab

Crontab Nedir?


Cron, istenilen işlerin belirli aralıklarla sistem arkaplanında çalışmasını sağlayan bir yardımcı yazılımdır. Crontab (CRON TABle - CRON TABlosu) çalıştırılacak cron elemanlarını ve ne zaman çalıştırılacaklarını tutan bir dosyadır.


Nasıl Çalışır?


Bir cron iş takvimi (schedule) basit bir ASCII metin dosyasıdır. Her kullanıcı kendi cron iş takvimine sahiptir. Bu genellikle Linux makinelerde /var/spool/cron/crontabs içinde bulunur. Crontab dosyaları direk olarak değiştirilemez ya da yaratılamaz. crontab komutunu kullanmadan dosyaya erişemezsiniz. 


$ crontab -e 


komutuyla crontab dosyasını düzenleyebilir ya da eğer yoksa yeni bir dosya oluşturabilirsiniz. Dosya sistemdeki varsayılan metin editörüyle açılacaktır. export EDITOR=vi ile vi'yi varsayılan editör yapabilirsiniz (ya da vi yerine istediğiniz editörü yazabilirsiniz). 

Bütün cron işleri en az 6 bölümden oluşur. Her bölüm tek boşlukla ayrılır. Son bölüm kendi içinde boşluklar barındırabilir. İlk 5 bölümde kendi aralarında kullanılması haricinde boşluğa izin verilmez. Bu ilk 5 Bölüm bir işin ne zaman ve hangi aralıklarla çalışacağını belirler. 



Bir işin genel yapısı şu şekildedir:


*   *   *   *   *       çalıştırılacak komut
-    -   -    -   -
|    |   |    |   |
|    |   |    |   +---- day of week - haftanın günü (0-7) (pazar için 0, isim kullanılabilir(ingilizce))
|    |   |    +-------- month - ay (1-12) (veya ay isimleri)
|    |   +------------- day of month - ayın günü (1-31)
|    +----------------- hour - saat (0-23)
+---------------------- minute - dakika (0-59)


Yıldız (*) o zaman birimindeki tüm geçerli değerlerin kullanılacağı anlamına gelir (her saat, haftanın her günü gibi). 


Bir zaman biriminde birden fazla değer kullanmak için değerleri virgülle (,) ayırmak gerekir. Eğer bir aralık girmek istiyorsanız başlangıç ve bitir tire (-) ile ayrılır. Örneğin, eğer komutunuzun pazartesiden cumaya her saat için :05 ve :35 geçe çalışmasını istiyorsanız girdiniz şu şekilde olmalıdır:


5,35 * * * 1-5 


Altıncı bölüm verilen zaman(lar)da çalıştırılacak komutu içerir. Örneğin, "temp" dizininizi her sabah 4:45'te temizlemek için:

45 4 * * * rm /home/{kullanıcı-ismi}/temp/*


Dosya kaydedildiği zaman çalışmaya başlar. Başlatmak için herhangi bir şey yapmanıza ya da bir program çalıştırmanıza gerek yoktur. Crontab dosyada bir komut olduğunda zamanı geldiğinde çalıştıracaktır. Bir girdinin/komutun çalışmasını istemediğinizde silmeniz ya da yorum satırı haline getirmeniz yeterlidir (başına # koyarak).


Crontab ile kullanılabilecek parametreler:

crontab -e    crobtab dosyasını düzenler, yoksa yeni bir tane yaratır
crontab -l     crontab dosyasını listeler
crontab -r     crontab dosyasını siler


Daha fazla bilgi ve örnek için man dosyasına bakabilirsiniz.


Öntanımlı olarak cron iş çalıştırıldıktan sonra kullanıcıya email gönderir. Bu özelliği kapatmak için her girdinin/işin sonuna 


> /dev/null 2>&1

eklenebilir.


Olayları bir log dosyasında toplamak içinse:


45  4 * * * rm /home/{kullanıcı-ismi}/temp/* > /home/{kullanıcı-ismi}/cronlogs/log.txt >/dev/null 2>&1

Log dosyasına yönlendirirken > kullanmak varolanı değiştirmek, >> kullanmak yeni girdiyi dosyanın sonuna eklemek anlamına gelir.




# komutları çalıştırmak için /bin/sh kullanılsın,
# /etc/passwd'de belirtilen önemsizdir
SHELL=/bin/sh
# kimin crontab’ı olduğunu boşver, bütün çıktıları ‘paul’e postala
MAILTO=paul
#
# hergün gece yarısından sonra beş dakika çalıştır
5 0 * * *       $HOME/bin/daily.job >> $HOME/tmp/out 2>&1
# her ayın ilk günü saat 14:15 de çalıştır -- çıktılar paul’e postalansın
15 14 1 * *     $HOME/bin/monthly
# hafta içi (Pazartesi-Cuma) hergün saat 22:00’da çalıştır ve Joe’yu kızdır
0 22 * * 1-5   mail -s "Saat 22:00" joe%Joe,%%Çocukların nerede?%
23 0-23/2 * * * echo "her gün 00:23, 02:23, 04:23 de çalışır"
5 4 * * sun     echo "her Pazar 4:05’de çalışır"


Bkn: [1]http://www.linuxweblog.com/crotab-tutorial
[2]http://adminschoice.com/crontab-quick-reference 
[3]http://www.belgeler.org/man/man5/man5-crontab.html


6 Kasım 2010 Cumartesi

PyQt'yi Etkileşimli(interactive) Kullanmak

    PyQt ile ilgili olarak Qt kodunun etkileşimli olarak kodlanabileceğini öğrendim. Qt'de yeni bir şeyler öğrenirken çok işe yarayabilecek bir özellik. Şöyle ki konsoldan python yazarak Python yorumlayıcısını açalım. 
    Şimdi basit bir pencere yaratalım(kodun kopyalanabilmesi için >>> kullanılmadı):
PyQt4.QtCore import *
from PyQt4.QtGui import *
app = QApplication([])
window = QWidget()
window.resize(400, 300)
window.show()
  
    Şöyle pencere göreceksiniz:
    Hadi bir buton ekleyelim:
button = QPushButton("Tikla!", window)
button.show()
  
    İşte interaktif şekilde butonumuzu ekledik:
    Şimdi de butonumuzu pencerenin ortasına alalım:

layout = QHBoxLayout(window)
layout.addWidget(button)

    Şimdi addStretch() özelliğinin görünüme etkisine bakalım:
layout.addStretch()


    Ve kolaylıkla butonumuzun tıklanma(clicked) özelliğine bir slot bağlayabiliriz(ifade biraz karışık oldu :| ):

def mySlot():
    print "Buton Tiklandi"
button.clicked.connect(mySlot)

    Görüldüğü üzere Qt'yi denemek için iyi bir yöntem.

Kaynak:http://pysnippet.blogspot.com/2010/11/getting-interactive-with-pyqt.html

5 Kasım 2010 Cuma

Python'da Socket Programlama


    Socketler ve portlar ağlarla ilgili çoğu programın temelini oluşturur. Soketler, bir tür süreçler arası haberleşme(interprocessing) yöntemidir. Soket, soyut bir tanımla haberleşme uç noktalarıdır. Pratik olarak soketler dosyalara benzer. Soketten okumak ile dosyadan okumak arasında hiçbir fark yoktur. Socketler için üç alan(domain) tanımlanmıştır:
    Unix Alanı/Dosya-Sistemi Alanı : Bu alandaki socketler bir sistemde iki veya daha süreç birbiriyle haberleşeceği zaman kullanılır. Socketler dosya sistemi içinde yaratılırlar. /var/lock/sock ya da /tmp/sock gibi yerel yolları içerecek şekilde string olarak gösterilirler
    İnternet Alanı : Bu alan TCP/IP üzerinden haberleşen süreçleri göstermektedir. Bu alanda yaratılan socketler (host, port) çiftleri şeklinde gösterilmektedir. Host, string ya da IP adresi şeklinde gösterilebilen host ismidir. Port ise o host üzerinde bağlanılacak portun sayısal değeridir.
    NS Alanı : Bu artık kullanılmayan Xerox protokolü üzerinden haberleşen süreçler için kullanılır.

    Bunlardan sadece ilk ikisi çoğunlukla kullanılmaktadır. Python hepsini destekler. Aşağıda TCP/IP socketleri kullanan bir uygulama yaratmak için gerekli adımlar sıralanmıştır:
    1. Socketi yaratmak (create)
    2. Sockete bağlanmak (connecting)
    3. Socketi bir adrese bağlamak (binding to an address)
    4. Bağlantıları dinlemek ve kabul etmek (listening and accepting connections)
    5. Veri göndermek/veri almak (transffering and recieveing  data)

    Bir socket yaratmadan önce kütüphanelerin yüklenmesi gerekir. socket modülü socketlerle çalışmak için gerekli herşeyi içerir.

    1. Socket Yaratmak
    Python'da socket yaratmak için socket() metodu kullanılır. 
socket(family, type, [protocol])
  • family : family parametresi socketin hangi alan için yaratıldığını belirtir. Birçok seçenek mevcuttur. Genel kullanılanlar ise Unix alanı için AF_UNIX ve internet alanı için AF_INET.
  • type : type kullanılacak protokol tipini belirtir. Tip TCP gibi bağlantı yönelimli (connection-oriented) ya da UDP gibi bağlantısız (connection-less) olabilir. TCP için SOCK_STREAM, UDP için SOCK_DGRAM sabitleri tanımlanmıştır. Diğer geçerli seçenekler ise SOCK_RAW, SOCK_SEQPACKET ve SOCK_RDM.
  • protokol : Bu parametre genellikle varsayılan değer olan 0 olarak bırakılır.
    Bunlar göz önüne alındığında internet alanı bir socket yaratmak için:
s = socket.socket(AF_INET, SOCK_STREAM)

    2. Sockete bağlanmak
    Yaratılan socketler sunucu-taraflı (server-side) ya da istemci-taraflı (client-side) olarak kullanılabilir. Sunucu-taraflı kullanılacaksa bir hosta bağlanması gerekir. Bunu socket nesnesinin connect() metodu ile gerçekleştiririz. connect() metodu host adresini ya da host adresi ve port numarasından oluşan (host, port) şeklinde bir ikiliyi kabul eder. Örneğin adresi 192.168.51.102 ve port numarası 8080 olan bir hosta bağlanmak için:
s.connect(("192.168.51.102", 8080))

    3. Socketi bir adrese bağlamak
    Eğer sunucu-taraflı kullanılacaksa socketin bir adres ve porta bağlanması gerekir. Bunun için bind() metodu kullanılır. bind() metodu parametre olarak socketin bağlanacağı adres ve gelen istekleri dinleyeceği port numarasından oluşan (host, port) şeklinde ikiliyi alır. Örnekse:
s.bind(("192.168.51.107, 8080))

    4. Bağlantı dinlemek ve kabul etmek
    Socket belli bir adrese bağlandıktan sonra, belirtilen porttan gelen istekleri dinlemek için görevlendirilmesi gerekir. Bu amaçla listen() metodu kullanılır. Parametre olarak kaç bağlantının kabul edileceğini alır. En az 1 olamalıdır. Aşağıda 2 bağlantı kabul edilmiştir:
s.listen(2)

    Yapılması gereken sonraki adım bağlantıları kabul etmektir. Bunun için accept() metodu kullanılır. Geriye istemciyi temsil eden bir socket nesnesi ve istemcinin adresini döndürür:
istemsock, adres = s.accept()

    5. Veri göndermek/veri almak
    Veri recv() ve send() metodlarıyla aktarılabilir. recv() metodu sunucu ya da istemciden gönderilen veriyi almak için kullanılır. Parametreler tampon boyu (buffer size) ve bayraklardır (flags). Bayraklar isteğe bağlıdır. Veri almak için kod:
tampon = 1024
s.recv(tampon)

    Veri göndermek içinse send() metodu çağrılır. Parametre olarak gönderilecek veri ve bayrak alır. Örnekse:
veri = raw_input(">>")
s.send(veri)

    Python'un socket dökümantasyonunda bulunan sunucu ve istemci örneğiyse şu şekilde:
    Sunucu:

# Echo server program
import socket
import sys

HOST = None               # Symbolic name meaning all available interfaces
PORT = 50007              # Arbitrary non-privileged port
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC,
                              socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
    af, socktype, proto, canonname, sa = res
    try:
        s = socket.socket(af, socktype, proto)
    except socket.error, msg:
        s = None
        continue
    try:
        s.bind(sa)
        s.listen(1)
    except socket.error, msg:
        s.close()
        s = None
        continue
    break
if s is None:
    print 'could not open socket'
    sys.exit(1)
conn, addr = s.accept()
print 'Connected by', addr
while 1:
    data = conn.recv(1024)
    if not data: break
    conn.send(data)
conn.close()

    İstemci:




# Echo client program
import socket
import sys

HOST = 'daring.cwi.nl'    # The remote host
PORT = 50007              # The same port as used by the server
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM):
    af, socktype, proto, canonname, sa = res
    try:
        s = socket.socket(af, socktype, proto)
    except socket.error, msg:
        s = None
        continue
    try:
        s.connect(sa)
    except socket.error, msg:
        s.close()
        s = None
        continue
    break
if s is None:
    print 'could not open socket'
    sys.exit(1)
s.send('Hello, world')
data = s.recv(1024)
s.close()
print 'Received', repr(data)


Kaynak ve Bknz:http://www.devshed.com/c/a/Python/Sockets-in-Python-Into-the-World-of-Python-Network-Programming/
http://docs.python.org/library/socket.html
http://cekirdek.uludag.org.tr/~meren/belgeler/socket/socket.htm

3 Kasım 2010 Çarşamba

Yerelde SVN Deposu Yaratmak

    Projelerinizdeki değişimleri takip edebilmek ve gerektiğinde eski bir duruma ulaşabilmek, projenin gelişimi sürecinde çoğu zaman ihtiyaç duyacağınız bir durumdur. Bunun için Subversion (SVN) kullanmak ve projelerinizi sürümlendirmek oldukça uygun ve güçlü bir yöntemdir. Biz de bu amaçla yerelde bir SVN deposunun nasıl yaratılacağına ve kullanılacağına bakacağız. Yaratacağımız depo tek kullanıcı tarafından kullanılacak ki bu da sizsiniz.

    Depoyu Yaratmak
    Öncelikle sisteminizde Subversion'un kurulu olduğundan emin almalısınız. $ svn --version komutuyla sistemde kurulu olup olmadığını görebilirsiniz. Eğer kurulu değilse $ sudo pisi it subversion komutuyla kurabilirsiniz. Şimdi ilk yapacağımız iş depomuzu yaratmak. Bunun için konsolda şu komutları veriyoruz:
    $ mkdir /home/user/svndepo                                #user yerine kullanıcı isminiz gelmeli
    $ cd ~/svndepo
    $ svnadmin create proje1

    Bu komutlarla kullanıcı dizininde tüm depolarımızı barındıracak "svndepo" isminde yeni bir dizin oluşturduk. Daha sonra bu dizine girdik. Hemen arkasından "svnadmin" komutuyla "proje" isimli depomuzu gerçekten yarattık. Depomuz şu anda boş ve uyarlama 0 (revision 0) durumunda. Depoya bazı veriler girer girmez bu durum değişecek. Şimdi yapmamız gereken depomuza başlangıç projemizi aktarmak:
    $ svn import /home/user/proje1 file:///home/user/svndepo/proje1/trunk -m "proje1'in ilk aktarımı"


    Bu komutla "proje1"in dosyalarını depoya aktardık(proje1'in /home/user/proje1'de olduğunu varsayalım). Proje dizininin sonuna "trunk" eklememizin sebebi bunun birçok Subversion kullanıcısı tarafından kullanılan bir dizin düzenleme geleneği olması. Son kısımsa SVN log 'da aktarmaya eklenecek bilgi içindir. Bu şekilde depomuzu yarattık ve dosyalarımızı aktardık. Şimdi verileri çekip çalışmaya başlamaya hazırız.

    Bir Çalışma Örneği Çekmek ve Çalışmaya Başlamak
    SVN kullanırken doğrudan depo üzerinde çalışmak yerine bir çalışma örneği çeker ve onun üzerinde çalışırsınız. Çalıma örneğini çekmek için:
    $ svn co file:///home/user/svndepo/proje1/trunk /home/user/proje1_calisma_ornegi


    Bu komut "/home/user/proje1_calısma_ornegi" dizini altında deponun bir çalışma örneğini oluşturacaktır. Artık çalışmalarımızı bu dizin/örnek üzerinde yapacağız. Değişiklikleri yaptıktan sonra depoya göndermemiz gerekecek. Çalışma dizininde oluğumuzu düşünürsek bunun için şu komutu vereceğiz:
    $ svn commit -m "degisikliklerle ilgili bilgi"


    Böylece değişiklikleri depoya göndermiş olduk.

Kaynak:http://www.guyrutenberg.com/2007/10/29/creating-local-svn-repository-home-repository/

SVN kullanımıyla ilgili:1 - http://tr.pardus-wiki.org/Pardus:Yeni_geli%C5%9Ftirici_k%C4%B1lavuzu#Subversion_kullan.C4.B1m.C4.B1
 2 - http://svnbook.red-bean.com/