Version Control

October 16, 2012

We looked at the make programmer’s tool in a previous exercise, and today we look at another programmer’s tool, a version control system. Version control systems allow programmers to keep multiple versions of text files in an economical manner, and there are many of them available: git, subversion, rcs, and the grand-daddy of all of them, sccs.

Our version control system provides three commands. Put takes a single filename argument, stores the file in a history file, and removes the original file from the file system; the history file has the same name as the original file with an added suffix .hist. Get takes a filename argument plus an optional version argument and writes to the file system the requested version of the file, defaulting to the current version of the file if no version number is given; versions are numbered 0 for the current version, 1 for the previous version, 2 for the version before that, and so on. Dir takes a single filename argument and shows a directory listing all available versions of a file. Unlike the bigger version control systems, there are no branches, only a single trunk of history.

The key to the version control system is the history file, which stores the most recent version of the file in its entirety, preceeded by a header line. Then follows a succession of deltas, one for each historical version, each preceeded by its own header line. Here’s a sample history file primes.ss.hist:

@@@ phil Mon Oct 15 18:52:22 CDT 2012 Factorization by trial division
(define (primes n)
  (let ((bits (make-vector (+ n 1) #t)))
    (let loop ((p 2) (ps (list)))
      (cond ((< n p) (reverse ps))
            ((vector-ref bits p)
              (do ((i p (+ i p))) ((< n i))
                (vector-set! bits i #f))
              (loop (+ p 1) (cons p ps)))
            (else (loop (+ p 1) ps))))))

(define (factors n)
  (let loop ((n n) (f 2) (fs (list)))
    (cond ((< n (* f f))
            (reverse (cons n fs)))
          ((zero? (modulo n f)
            (loop (/ n f) f (cons f fs)))
          (else (loop n (+ f 1) fs)))))
@@@ phil Mon Oct 15 18:50:32 CDT 2012 Fix typo s/vectr/vector
10,17d
@@@ phil Mon Oct 15 18:49:57 CDT 2012 Sieve of Eratosthenes
7c
                (vectr-set! bits i #f))
.

The header line that preceeds each delta, including the current file version, starts with three asterisks. Then comes the name of the user that created the delta, and the date and time when it was created. The rest of the line is a comment written by the user when the delta is added to the history file.

Deltas are computed by the Unix diff command with the -e option (we wrote our own version in a previous exercise) comparing the old and new versions and applied by the Unix ed command by applying edit commands to the newest version to recreate older versions. We also use the Unix wc command to count the lines in a delta.

Your task is to write a version control system as described above. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Advertisement

Pages: 1 2