Fossil: Source Code Management reloaded.

An ideal introduction to the ultimate Source Management System featuring:

Tutorial Details

Step 1

Fossil has some features that make it unique, confronting other source code versioning systems. For example, if you know Subversion, you know that hosting is usually quite expensive. Often you need an ssh access, so you have to take into account many security issues. Also WebDAV is not available to anyone or very easy to get working. Many other free software SCM provide an http-operating mode, but they need configuration tricks that are not really straightforward nor out-of-the-box. Fossil uses the HTTP protocol by default, so you don't need a shell to repository your code any more. It works out of the box solving many of the problems that most developers face everyday. Many webdesigner not accustomed to use SCM systems via shell could get now a new, great chance now with fossil. Fossil is also a multi-repo system, so you can keep track of multiple branches, beside being able of versioning code in offline mode. Fossil is mainly based on the robust SQLite3 database engine; any data is stored into a portable database file. It is also written by the author of SQLite, Dr. R. Hipps. Another great thing about Fossil is that is all into a single self-contained executable file. So the program itself does not need a real installation, you need only to copy one file on your system and add it to your path. The installation can be done copying the right executable for your platform. These are available from here Fossil itself could be downloaded in sources form from its Fossil's repository:

fossil clone http://www.fossil-scm.org/ myclone.fossil
My advice is to take the precompiled version to experiment, and then to switch to the last one to compile by yourself.

Step

For those accustomed to the idea of using a Versioning System, they should be concerned with the concept of Checkout. In Fossil, any local operation is performed is only made after getting a local copy of the repository itself. So we have a previous CLONE command. For example, to clone a remote repository:

	fossil clone http://code.lulli.net/index.cgi code.fossil
Now you have the file code.fossil which is a local code of the remote repository. Actually, it is a SQLite3 file which contains metadata about the downloaded project. If you have SQLite3 installed, you could take a look making:
	$ sqlite3 code.fossil
And giving sqlite commands. For example, you could take a look at tables schema giving:
	$ sqlite3 code.fossil .schema
CREATE TABLE blob(
  rid INTEGER PRIMARY KEY,
  rcvid INTEGER,
  size INTEGER,
  uuid TEXT UNIQUE NOT NULL,
  content BLOB,
  CHECK( length(uuid)==40 AND rid>0 )
);
CREATE TABLE concealed(
  hash TEXT PRIMARY KEY,
  content TEXT
);
CREATE TABLE config(
  name TEXT PRIMARY KEY NOT NULL,
  value CLOB,
  CHECK( typeof(name)='text' AND length(name)>=1 )
);
CREATE TABLE delta(
  rid INTEGER PRIMARY KEY,
  srcid INTEGER NOT NULL REFERENCES blob
);
CREATE TABLE event(
  type TEXT,
  mtime DATETIME,
  objid INTEGER PRIMARY KEY,
  tagid INTEGER,
  uid INTEGER REFERENCES user,
  bgcolor TEXT,
  euser TEXT,
  user TEXT,
  ecomment TEXT,
  comment TEXT,
  brief TEXT
);
CREATE TABLE filename(
  fnid INTEGER PRIMARY KEY,
  name TEXT UNIQUE
);
CREATE TABLE mlink(
  mid INTEGER REFERENCES blob,
  pid INTEGER REFERENCES blob,
  fid INTEGER REFERENCES blob,
  fnid INTEGER REFERENCES filename,
  pfnid INTEGER REFERENCES filename
);
CREATE TABLE phantom(
  rid INTEGER PRIMARY KEY
);
CREATE TABLE plink(
  pid INTEGER REFERENCES blob,
  cid INTEGER REFERENCES blob,
  isprim BOOLEAN,
  mtime DATETIME,
  UNIQUE(pid, cid)
);
CREATE TABLE private(rid INTEGER PRIMARY KEY);
CREATE TABLE rcvfrom(
  rcvid INTEGER PRIMARY KEY,
  uid INTEGER REFERENCES user,
  mtime DATETIME,
  nonce TEXT UNIQUE,
  ipaddr TEXT
);
CREATE TABLE reportfmt(
   rn integer primary key,
   owner text,
   title text,
   cols text,
   sqlcode text
);
CREATE TABLE shun(uuid UNIQUE);
CREATE TABLE tag(
  tagid INTEGER PRIMARY KEY,
  tagname TEXT UNIQUE
);
CREATE TABLE tagxref(
  tagid INTEGER REFERENCES tag,
  tagtype INTEGER,
  srcid INTEGER REFERENCES blob,
  origid INTEGER REFERENCES blob,
  value TEXT,
  mtime TIMESTAMP,
  rid INTEGER REFERENCE blob,
  UNIQUE(rid, tagid)
);
CREATE TABLE ticket(
  -- Do not change any column that begins with tkt_
  tkt_id INTEGER PRIMARY KEY,
  tkt_uuid TEXT UNIQUE,
  tkt_mtime DATE,
  -- Add as many field as required below this line
  type TEXT,
  status TEXT,
  subsystem TEXT,
  priority TEXT,
  severity TEXT,
  foundin TEXT,
  private_contact TEXT,
  resolution TEXT,
  title TEXT,
  comment TEXT
);
CREATE TABLE unclustered(
  rid INTEGER PRIMARY KEY
);
CREATE TABLE unsent(
  rid INTEGER PRIMARY KEY
);
CREATE TABLE user(
  uid INTEGER PRIMARY KEY,
  login TEXT,
  pw TEXT,
  cap TEXT,
  cookie TEXT,
  ipaddr TEXT,
  cexpire DATETIME,
  info TEXT,
  photo BLOB
);
CREATE INDEX delta_i1 ON delta(srcid);
CREATE INDEX event_i1 ON event(mtime);
CREATE INDEX mlink_i1 ON mlink(mid);
CREATE INDEX mlink_i2 ON mlink(fnid);
CREATE INDEX mlink_i3 ON mlink(fid);
CREATE INDEX mlink_i4 ON mlink(pid);
CREATE INDEX plink_i2 ON plink(cid);
CREATE INDEX tagxref_i1 ON tagxref(tagid, mtime);
Apart from the (very interesting) internals, you can go on using Fossil extrancting code in your work directory; assuming the following tree
work/
work/code
work/repository/code.fossil
you can change directory to
work/code
and checking out code in there by giving on the commandline:
$ cd work/code
$ fossil open ../repository/code.fossil
You will seee something like:
GNUstep/Zero/GNUmakefile
GNUstep/Zero/GNUmakefile.postamble
GNUstep/Zero/GNUmakefile.preamble
GNUstep/Zero/ZeroController.c
GNUstep/Zero/obj/ZeroController.c
GNUstep/Zero/shared_obj/ZeroController.c
GNUstep/Zero/zero.app/Resources/Info-gnustep.plist
GNUstep/Zero/zero.app/Resources/zero.desktop
GNUstep/Zero/zero.app/library_paths.openapp
GNUstep/Zero/zero.app/stamp.make
GNUstep/Zero/zero.app/zero
GNUstep/Zero/zero.pmproj
GNUstep/Zero/zeroInfo.plist
GNUstep/dot.profile_linux.sh
ci-comment-DBD2EFA2CEEB.txt
crud/Aa.js
crud/Aei.js
crud/TestZero.js
crud/auth/add_block.inc
crud/auth/add_user.inc
.
.
.
project-name: Code
repository:   /home/blacksheep/work/repository/code_local.fsl
local-root:   /home/blacksheep/work/code/
project-code: 287ab3c91d1c0b3acec75b1349bdbca4637fa0a8
server-code:  87a2393f5da7cc71360c959176c5ac85fa449669
checkout:     6ffe9aeef0c43281c7a023a5598642669680eead 2010-02-12 19:29:55 UTC
parent:       2384b70a29cbacc79afb5e57076d1d75665b5fdd 2010-02-12 18:27:41 UTC
tags:         trunk
Now you have a working checkout within your working directory. You can work on it.

Step 2

While you may be interested on a local setup, it is now time to learn setting up a remote server to upload your work on. You can choose now between creating the new repository on your local machine and uploading on the remote one or, if you've got a remote shell, you could create it already on the remote machine via ssh, for example:

$ ssh devman@my.remotemachine.com
devman@remotemachine$ 
devman@remotemachine$ fossil new MYREPO.fsl
project-id: a97eae2a62cdf5481a19a5dce6c9ab
3e2c763d0e
server-id:  f26a799c43f6d82a99d1119b26a98567e0d04697
admin-user: devman (initial password is "b752cd")
You'd better take note of these credentials, as they will be needed to later access with that user. So, I' advice you to make something slightly different from above:
devman@remotemachine$ fossil new MYREPO.fsl > credentials.txt
This way, you're saving useful credentials on a text file for later memory. Obviously, is up to you to move them away in some place where unwanted people cannot read. Then you reference this remote repository file within a CGI:
devman@remotemachine$ chmod 755 $HOME/www/index.cgi
devman@remotemachine$ cat $HOME/www/index.cgi
#! /usr/local/bin/fossil
repository: /home/devman/MYREPO.fsl
This should be on the document root of your web server, for example Apache's
htdocs
From this setup, anything looks like I can checkout (actually: clone) the remote repository in a local directory. Provided that you have the script above available on the web pointing the browser to:
http://hackbook.org/code/index.cgi
So, back on my local shell, I can get the remote data...
user@localmachine$ mkdir $HOME/repo
user@localmachine$ cd $HOME/repo
user@localmachine$ fossil clone   http://hackbook.org/code/index.cgi LOCALrepo.fsl
Bytes      Cards  Artifacts     Deltas
Send:             597         24          0          0
Received:           0          0          0          0
Total network traffic: 472 bytes sent, 464 bytes received
Rebuilding repository meta-data...
0 (0%)...
project-id: a97eae2a62cdf5481a19a5dce6c9a
server-id:  75cf3cfbb2855595de5874459f239c55b71218ee
admin-user: devman (password is "1a4411")
Here we go again, give on the command line:
user@localmachine$ fossil open $HOME/repo/LOCALrepo.fsl
and start adding code; For example:
user@localmachine$ mkdir A
user@localmachine$ echo "A new File">> A/try.txt
user@localmachine$ fossil add A
user@localmachine$ fossil commit
This way, in the repository I will find the file A/try.txt.

Step 3

About the development cycle, the so-called Checkin/checkout and remote setup, we have still to talk about the web interface. While most of SCM systems only provide a commandline interface to checkin/checkout, Fossil provides you out-of-the-box a web administration interface. It can either be run via CGI, as we already saw, or via its own, embedded webserver. You can run it on the local repository file simply giving:

user@localmachine$ fossil ui  code.fossil
It will open a web console you could access at: 
http://localhost:8081/index
While you could open the remote one we started before at:
http://hackbook.org/code/index.cgi
Under the local gui (fossil ui) I can now see under FILES, the file A/try.txt that we uploaded before. From the web GUI you can set permissions; for example, if you do not provide credentials other than Anonymous, you cannot clone the remote repository. By accessing the web console to the admin tab:

you can set the permission you need for that user. The permission to clone a repository is identified by the letter g Even more, you can create new users. Each user can have different roles.

As you see, Fossil lets you implement different and tailor-made access policies. If you lived behind a proxy, you may have to set :
user@localmachine$ export http_proxy=http://localhost:3128
Then, you pull local repository changes to the remote one this way:

Step 4

You now have almost any command that you need to:

You should add to these the commands to push and retrieve changes from the remote repository, as Fossil is a multi-repository system.
user@localmachine$ fossil push  http://hackbook.org/code/index.cgi
and take back (eventual) remote ones via :
user@localmachine$ fossil pull  http://hackbook.org/code/index.cgi
both operations are performed making:
user@localmachine$ fossil sync
To all these command I'd add the help:
user@localmachine$ fossil help

CopyLeft by Paolo Lulli 2010