Trace: • subversion
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
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) 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:
<Location /svn> DAV svn # any "/svn/foo" URL will map to a repository /home/svn/foo SVNParentPath /home/svn </Location>
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:
<Location /svn> 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 </Location>
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 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:
<Location /svn> 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. <LimitExcept GET PROPFIND OPTIONS REPORT> Require valid-user </LimitExcept> </Location>
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”.
You are here: start » linux » subversion