=====Subversion=====
Through the use YUM, I have installed subversion:
Name : subversion
Arch : i386
Version: 1.2.1
Release: 0.1.1.fc2.rf
Size : 7.82 MB
Group : Development/Tools
Repo : Locally Installed
Summary: A Concurrent Versioning system similar to, but better than, CVS.
Description:
Subversion is a concurrent version control system which enables one or more
users to collaborate in developing and maintaining a hierarchy of files and
directories while keeping a history of all changes. Subversion only stores
the differences between versions, instead of every complete file. Subversion
also keeps a log of who, when, and why changes occured.
I am going to use subversion to ease the development of //Ruby on Rails //projects. Installing Ruby on Rails is the subject of another section.
===Extending the YUM repository list===
You will not find the latest version of subversion packaged in Fedora Core 2. Fortunately, there are some serious packagers out there:
[[http://dag.wieers.com/home-made/apt/FAQ.php#B4|http://dag.wieers.com/home-made/apt/FAQ.php#B4]]
To have the YUM installer look in other repositories, go to: ''**/etc/yum.conf**'', and add (for example) the following entry:
[dag]
name=Dag RPM Repository for Fedora Core
baseurl=http://apt.sw.be/fedora/$releasever/en/$basearch/dag
gpgcheck=0
enabled=1
The next time you issue the command ''**yum info**'' ''**subversion**'', yum will look for updates and new packages in the url you just added.
===Installing Apache 2===
Subversion works best in combination with Apache 2. Since I already have Apache 1.3 installed, this requires some fine tuning.
Apache 2 must be made to listen only to port 8080, which will be the port we are going to use for Subversion. As an added bonus, we could do some php5 experiments on Apache 2.
First, I installed Apache2 through Yum:
[root@1038 root]# yum install httpd
Gathering header information file(s) from server(s)
Server: Fedora Linux 2 - i386 - core
Server: Dag RPM Repository for Fedora Core
Server: Fedora Linux 2 - i386 - freshrpms
Server: Fedora Linux 2 - i386 - updates
Finding updated packages
Downloading needed headers
Resolving dependencies
Dependencies resolved
I will do the following:
[install: httpd 2.0.51-2.9.i386]
Is this ok [y/N]: y
Downloading Packages
Getting httpd-2.0.51-2.9.i386.rpm
httpd-2.0.51-2.9.i386.rpm 100% |=========================| 905 kB 00:00
Running test transaction:
Test transaction complete, Success!
httpd 100 % done 1/1
Installed: httpd 2.0.51-2.9.i386
Transaction(s) Complete
Here's the location of the daemon:
[root@1038 root]# find / -name httpd
/etc/httpd
/etc/logrotate.d/httpd
/etc/rc.d/init.d/httpd
/home/httpd
/var/tmp/bind/httpd
/var/tmp/.i/.i/httpd
/var/tmp/www/httpd
/var/log/httpd
/www/bin/httpd
/usr/lib/httpd
/usr/src/apache_1.3.33/src/httpd
/usr/sbin/httpd
[root@1038 root]# cd /usr/sbin
The location of the httpd.conf file:
[root@1038 sbin]# find / -name httpd.conf
/etc/httpd/conf/httpd.conf
/www/conf/httpd.conf
And the control utility:
[root@1038 sbin]# find / -name apachectl
/www/bin/apachectl
/usr/src/apache_1.3.33/src/support/apachectl
/usr/sbin/apachectl
[root@1038 sbin]# /usr/sbin/apachectl start
This works.
===Installing mod_dav_svn===
According to the documentation in a book ([[http://svnbook.red-bean.com/en/1.1/svn-book.html#svn-ch-6-sect-4.1|http://svnbook.red-bean.com/en/1.1/svn-book.html#svn-ch-6-sect-4.1]]) about Subversion, you also need a special module, mod_dav_svn:
[root@1038 modules]# yum install mod_dav_svn
Gathering header information file(s) from server(s)
Server: Fedora Linux 2 - i386 - core
Server: Dag RPM Repository for Fedora Core
Server: Fedora Linux 2 - i386 - freshrpms
Server: Fedora Linux 2 - i386 - updates
Finding updated packages
Downloading needed headers
Resolving dependencies
Dependencies resolved
I will do the following:
[install: mod_dav_svn 1.2.1-0.1.1.fc2.rf.i386]
Is this ok [y/N]: y
Downloading Packages
Getting mod_dav_svn-1.2.1-0.1.1.fc2.rf.i386.rpm
mod_dav_svn-1.2.1-0.1.1.f 100% |=========================| 60 kB 00:00
Running test transaction:
Test transaction complete, Success!
mod_dav_svn 100 % done 1/1
Installed: mod_dav_svn 1.2.1-0.1.1.fc2.rf.i386
Transaction(s) Complete
===Neon===
Apparently, you also need Neon, "An HTTP and WebDAV client library", but this was already installed on my system:
[root@1038 modules]# yum info neon
Gathering header information file(s) from server(s)
Server: Fedora Linux 2 - i386 - core
Server: Dag RPM Repository for Fedora Core
Server: Fedora Linux 2 - i386 - freshrpms
Server: Fedora Linux 2 - i386 - updates
Finding updated packages
Downloading needed headers
Looking in Available Packages:
Looking in Installed Packages:
Name : neon
Arch : i386
Version: 0.24.7
Release: 2.1
Size : 190.44 kB
Group : Applications/Publishing
Repo : Locally Installed
Summary: An HTTP and WebDAV client library
Description:
neon is an HTTP and WebDAV client library, with a C interface;
providing a high-level interface to HTTP and WebDAV methods along
with a low-level interface for HTTP request handling. neon
supports persistent connections, proxy servers, basic, digest and
Kerberos authentication, and has complete SSL support.
====Configuring subversion====
Configuring subversion starts with configuring Apache, through ''**httpd.conf**''. In my case, I have also Apache 1.3 running. So I need my Apache 2 installation to listen only to port 8080:
Listen 8080
With regard to subversion, you need to make sure the necessary Apache modules are loaded:
LoadModule dav_module modules/mod_dav.so
LoadModule dav_svn_module modules/mod_dav_svn.so
Then, Apache must be told to delegate all svn related stuff to somewhere else:
DAV svn
# any "/svn/foo" URL will map to a repository /home/svn/foo
SVNParentPath /home/svn
This means that all repositories will end up under ''**/home/svn**''. From the book:
//This is a particularly convenient syntax in that, unlike the use of the SVNPath directive, you don't have to restart Apache in order to create and network new repositories.//// //
===Backups===
I have created my SVN Parent Path under ''**home**'', because all contents of ''**home**'' are automatically part of backup. My backup scripts simply compress and copy files to a tar archive. The problem is that such a backup system could lead to corrupted backups if you use it to backup databases.
So, to avoid any problems, I do not use the (non-default) BerkeleyDB database for my repositories, but instead //FSFS//:
'An FSFS repository stores a revision tree in a single file, and so all of a repository's revisions can be found in a single subdirectory full of numbered files. Transactions are created in separate subdirectories. When complete, a single transaction file is created and moved to the revisions directory, thus guaranteeing that commits are atomic. And because a revision file is permanent and unchanging, the repository also can be backed up while "hot" (..).'
One of the main advantages of FSFS (over BerkeleyDB) is that it is not very sensitive to interruptions (such as those caused by making backups).
===Security===
SVN is controlled by Apache. There is, as far as I can see, no need for any user but Apache to gain access to the repositories, so after creating a repository, I issue the command:
[root@1038 svn]# chown apache:apache -R repos
I have also secured the /home/svn directory, using standard Apache authentication tools:
[root@1038 svn]# htpasswd -cm /etc/svn-auth-file onno
New password:
Re-type new password:
Adding password for user onno
*First time: use -c to create the file
*Use -m to use MD5 encryption of the password, which is more secure
And in Apache's httpd.conf:
DAV svn
# any "/svn/foo" URL will map to a repository /home/svn/foo
SVNParentPath /home/svn
AuthType Basic
## AuthName is an arbitrary name that you give for the authentication domain
AuthName "Subversion repository"
AuthUserFile /etc/svn-auth-file
## tell Apache that all requests require an authenticated user
Require valid-user
====Using subversion for a new project====
Create a new repository:
[root@1038 sbin]# svnadmin create /home/svn/repos
[root@1038 sbin]# ls /home/svn/repos
conf dav db format hooks locks README.txt
This creates a directory structure containing a database for your repository. Do not forget to set permissions and ownership. Usually, apache is the user (if you're accessing svn through http), so you'd do something like:
[root@1038 svn]# chown -R apache:apache smallcount
To delete a repository, simply delete the parent directory and all its contents:
[root@1038 sbin]# rm -Rf /home/svn/repos
Warning: all contents will be gone forever!
===About Subversion clients===
You can use any client you like, but for Windows **TortoiseSVN** is an excellent choice. Use this tool to populate your repository by clicking "import" in the context menu (assuming of course that you already have a subversioned project). As you can see from this example, this particular client assumes that we are thinking from the perspective of the SVN //server//. After all, from my point of view, I am //exporting //data to the server.
===Populating a repository: creating a new project===
To actually fill your repository with data which should be under version control, use TortoiseSVN on your local machine. Rightclick the folder which is the data source. Then choose "import" (on the CLI, move into the folder which contains your data source, then type ''svn import . repository_url -m "Import" --username user''). Now, following the example above, under repository fill in:
http://yourdomain.com:8080/svn/repos
Start your project with the following directory structure:
repos
repos/tags
repos/branches
repos/trunk
(Or use 'my_project' instead of repos, if that's an easier example).
Make these directories on your local system (in a temporary directory) and then "import" them to the "repos" repository. Using the command line:
$ svn import -m 'New import' /home/me/repos http://yourdomain.com:8080/svn/repos
(Do NOT forget to use svnadmin first, on the svn server, before attempting this!)
Your main development version will be in trunk. Create a "repos" directory on your local system, and do a "checkout": rightclick on the local "repos" directory (still assuming you're using TortoiseSVN) and choose "checkout". In the address bar, still following our example, fill in this:
http://yourdomain.com:8080/svn/repos/trunk
As you can see, we have descended into the repository's trunk directory, because locally we're working on the development version, which goes into "trunk".
===Importing an Existing Project into Repository===
If you already have an existing application which you want to bring into subversion, use this:
svn import -m 'Importing actual application' /home/me/repos http://yourdomain.com:8080/svn/repos/trunk
Of course, this is exactly the same command, except that your now specifying the trunk directory, which is where you want your development version to be.
===Getting data out of a repository: checkout===
Extracting the data from a repository is called "checking out". In TortoiseSVN, simply rightclick on the destination folder on your local machine. Then choose "SVN Checkout", and under repository (still following the example) fill in:
http://yourdomain.com:8080/svn/repos
On the command line (e.g. on your Linux machine) you would use the svn client to do a checkout. Because you're not clicking on any subdirectory, you have to specify the destination:
svn checkout http://yourdomain.com:8080/svn/myweb/trunk/ myweb
(Or use svn checkout http://yourdomain.com:8080/svn/myweb/trunk/ .
if you are already inside the ''myweb'' directory)
This command will pour the contents of ''**trunk**'' into the "''**myweb**''" directory. Using Linux, do not forget to specify ownership and permissions afterwards.
===Updating a working copy===
Move //into// the top level directory which contains your working copy. The execute this command:
svn update
Always run ''**svn update**'' //before// you commit, to make sure your file is up to date. Otherwise, you risk overwriting changes that other people have done in the meantime.
Clarification: a working copy is on the "client side". Here, you use svn as a client tool.
===Having svn ignore configuration files and such===
Some files must never be updated, for example those containing local configuration settings. Here is an example how you use svn to ignore these files:
svn propset svn:ignore database.yml config
This means: add the ignore property for the file "database.yml" to the directory "config".
To check which files are ignored, issue this command:
svn status --no-ignore
Here is some example output:
[root@1038 woordenweb]# svn status --no-ignore
I tmp/sessions/ruby_sess.2278e7e31b8ecb57
I tmp/sessions/ruby_sess.1a93b2ffb6b792db
I tmp/sessions/ruby_sess.00da84c455b6ee76
I tmp/sessions/ruby_sess.8aef2d83126b8a7b
I log/fastcgi.crash.log
I log/development.log
I config/database.yml
M public/dispatch.cgi
M public/dispatch.rb
M public/dispatch.fcgi
And to ignore all files in a directory:
svn propset svn:ignore "*" public/
Or all files in subdirectories:
svn propset svn:ignore "*" tmp/sessions tmp/cache tmp/sockets
Or all *.log files in a directory called "log":
svn propset svn:ignore "*.log" log/
Or all *.marks files in all directories (through the use of a wildcard and the -R recursive option):
svn propset svn:ignore -R "*.marks" */
See also [[http://wiki.rubyonrails.org/rails/pages/HowtoUseRailsWithSubversion|How to Use Rails With Subversion]].
===Excluding multiple directories===
To ignore multiple types of files and folders, you must have a newline delimited list of values for the svn propset command. Because this can not be done with the commandline (well, I do not know how to do it anyway), we create a text file with on each line the signature of a file and/or folder to ignore.
For example, we have a textfile with following content:
obj
bin
We save this file in the target folder and name it “ignore.txt”, and then issue the command in the target folder
[TargetFolder]>svn propset svn:ignore -F ignore.txt .
Do not forget the final dot, it means that the target folder is the current folder. With the above command all folders with names obj and bin in the target folder will be ignored by Subversion.
Another example:
onno@onno-desktop:~/rails/games/public/images$ cat > temp.txt
thumbnails
picturesonno@onno-desktop:~/rails/games/public/images$ ls -lah
total 36K
drwxr-xr-x 7 onno onno 4.0K 2008-08-28 21:24 .
drwxr-xr-x 6 onno onno 4.0K 2008-08-26 16:49 ..
drwxr-xr-x 4 onno onno 4.0K 2008-08-27 21:39 dummies
drwxr-xr-x 2 onno onno 4.0K 2007-06-27 09:18 kropper
drwxr-xr-x 3 onno onno 4.0K 2008-08-25 22:31 pictures
-rw-r--r-- 1 onno onno 1.8K 2008-07-18 10:18 rails.png
drwxr-xr-x 6 onno onno 4.0K 2008-08-28 21:23 .svn
-rw-r--r-- 1 onno onno 19 2008-08-28 21:24 temp.txt
drwxr-xr-x 3 onno onno 4.0K 2008-08-26 14:43 thumbnails
onno@onno-desktop:~/rails/games/public/images$ svn propset svn:ignore -F temp.txt .
property 'svn:ignore' set on '.'
onno@onno-desktop:~/rails/games/public/images$ svn commit -m "Ignoring both dirs thumbnails and pictures in svn"
Sending images
Committed revision 54.
onno@onno-desktop:~/rails/games/public/images$ svn status
? kropper
? temp.txt
onno@onno-desktop:~/rails/games/public/images$
====Anonymous, Readonly Repository====
If you publish your Rails plugins, you may want to restrict access to the svn repository: only you are allowed to make commits. Everybody else has just readonly (checkout) rights. Here's how to configure Apache:
DAV svn
SVNParentPath /usr/local/svn
# how to authenticate a user
AuthType Basic
AuthName "Subversion repository"
AuthUserFile /path/to/users/file
# For any operations other than these, require an authenticated user.
Require valid-user
This is the same procedure used for normal authentication. The only difference is that here, you're saying: "for any other operations than readonly, require an authenticated user".