diff options
Diffstat (limited to 'rvs/HACKING')
-rw-r--r-- | rvs/HACKING | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/rvs/HACKING b/rvs/HACKING new file mode 100644 index 0000000..a198138 --- /dev/null +++ b/rvs/HACKING @@ -0,0 +1,295 @@ +#!/bin/more + + Version 0.8c reimplements the wrapper in C, to allow better + cooperation betweem plugins via dependancies. This probably makes + a lot of this document out-dated, but a lot of it is still good, it + describes the workings of the plugins, and the repo structure. + + I know this file is long* and boring. I try to keep it preened and + informative, but would rather spend my time actually hacking. If + you think you can help this file, have at it! ~ Luke Shumaker + + * at 200+ lines, it's longer than any rvs source file + +- - -cut-here- - 8< - - - - - - - - - - - - - - - - - - - - - - - - - +////////////////////////////////////////////////////////////////////// + rvs 0.7.0 + retroactive versioning system + a versioning system that allows you to check + in commit 2 before commit 1 +////////////////////////////////////////////////////////////////////// + + hacking + + build basics + + One of the coolest things about rvs (imo) is how modular and + customizable it is. If you wish to create a fork of rvs, it wls ould + be a good idea to give it a different name. This can be done + without even changing a single source file! Simply run configure + with `--name=NAME' option (variables that have `rvs' in the name + will not be renamed, but the user will never know this unless they + peek ath the code). + + Other options to configure and their default values are: + name='rvs' + The name of the program. Note that unlike most + variables, you should NOT call this in Makefiles + (`$(name)'), but use `$(rvs)' instead. + RVS='$(bindir)/$(rvs)' + Where the exectuable will be. `$(rvs)' is the same as + `$(name)' (see above). In this document it is + sometimes reffered to as the `wrapper'. + SHELL='/bin/sh' + The shell that will be used by make, and the shell + that scripts will run in. (Perhaps we should make + these separate variables?) + prefix='/usr/local' + Standard GNU variable. Many of you will want to + change this to `/usr', or `/home/USER_NAME' + exec_prefix='$(prefix)' + Standard GNU variable. + bindir='$(exec_prefix)/bin' + Standard GNU variable. + sbindir='$(exec_prefix)/sbin' + Standard GNU variable. + libexecdir='$(exec_prefix)/libexec' + Standard GNU variable. The plugins will be installed + at $(libexecdir)/$(name) + srcdir=$(readlink -f `dirname "$0"`) + Where the source code is. The default value evaluates + to the directory of the `configure' script. + + These can either be changed by manually changing `configure' or by + running it like: + ./configure --VAR_NAME=VALUE + + In this document, the `$(VAR_NAME)' refers to whatever you set the + value to. + + The configure script will run on any instance of `Makefile.in' in + $(srcdir). + + Currently, rvs is distributed with 2 pluggins. `repo'(sitory) is + the core of the rvs file database. `users' handles all usernames, + settings, and other info. + + commands + + By itself, rvs does almost nothing. All real functionality is + provided by plugins. When you invoke rvs, you do so in the format + `rvs COMMAND'. Plugins work by adding new commands. + + Most commands are provided by plugins, however, a few are built in: + init + Initializes a repository in the current directory. It creates + `./.$(name)', and runs any initalizers for + plugins. + install PLUGIN DIR + Installs PLUGIN, for which the files are found in DIR. Unless + an older version is already installed, it adds the plugin to + have lowest priority (see `$(libexecdir)/$(rvs)/plugins'). + uninstall PLUGIN + Uninstalls PLUGIN. Did that really need to be said? + + A plugin is simply a collection of independant executable files. + When rvs is invoked, it looks for the COMMAND in a few places: + 1) checks if COMMAND is an built-in command + 2) looks at the file `$(libexecdir)/$(rvs)/plugins'. This is a + newline-delimited list of plugin names. + 3) loops through the directories `$(libexecdir)/$(rvs)/PLUGIN', + where PLUGIN is one of the values in + `$(libexecdir)/$(rvs)/plugins', in the order they appear in + the file. + 4) if rvs does not find the command, it reports an error + + + If you would like to contribute a plugin, or distribute one with a + fork, all you have to do is put it in `$(srcdir)/plugins/NAME'. The + main Makefile will recognize any directory in `$(srcdir)/plugins/' + as a plugin, and will run `make -C `plugins/NAME/Makefile'. It + should create a directory (mine use `plugins/NAME/out') to put ALL, + and ONLY the final files to be used by that plugin. + +========this is outdated but I don't really want to keep editing it == + + build system + + The build system rvs uses is rather simple. + `./configure' does two things: + * create a sed script (`var.sed') + * run every incance of `$(srcdir)/Makefile.in' through + `var.sed' to generate a propper `Makefile' + + `var.sed' contains all configuration variables. When it processes + a file every instance of `@VAR_NAME@' is replaced by that + variable's value. This makes `configure' act much like a GNU + package `congfigure'. Note that this replacement only happens for + defined variables. + + Most of these can easily be changed _after_ `compilation' also: + VER line 4 of the wrapper + SHELL line 1 of each shell script + prefix simply move the wrapper + bindir simply move the wrapper + libexecdir move the directory, then update the line + `RVSDIR=...' in the wrapper + + I have designed this system to be extremely modular. As you may + have figured out, each bit on functionality is in it's own + executable, and the file you call when you type `rvs' is just a + wrapper for them. + + The wrapper is quite simple in mechanism. It simply checks if + `$$libdir$$/COMMAND_NAME' exists, and if so, runs that file. + + The `rvs commit' command is also quite simple in design. It takes a + single argument; the file to commit. If no target is specified, it + defaults to `./'. It checks which type of file the target is, and + runs `rvs commit.FILE_CODE TARGET'. The file codes are as follows: + + block (buffered) special b + character (unbuffered) special c + directory d + named pipe (FIFO) p + regular file f + symbolic link l + socket s + door (Solaris only) D + + As you probably noticed (if you've looked at the blueprints or + source files), only directories and regular files have been + implemented as of rvs 0.7.0. + + After `rvs commit' has done this, it creates a meta-file for that + commit. The meta file contains author, copyright owner, licence + data, file permissions, timestamps, etc. The id of the meta-file is + written to stdout, and used to later check out that commit. + + get works in much the same way as commit, only it reads the file + type from the meta-file, then runs `rvs get.FILE_CODE COMMIT_ID'. + + If you implement any other file types, save the commit and get + functions in the propper locations. + + Any commit function should take a filename as an argument and + output the according commit id to stdout. stderr should be used + for all messages. + + Any get function should take the commit id as an argument and + uses stdout only if verbose, or to report errors. + + To summarize, the modules are separate programs and communicate via + pipes, which is generally considered bad-design, and libraries + should be used instead. I deliberatly broke this because: + + 1. incompatible licences can be used for different modules + 2. modules can be added/removed on the fly + 3. one can use any language to write new modules, without + having to worry about bindings`$(libexecdir)/$(rvs) + + $$libdir$$/lib/ + THIS WAS WRITTEN FOR rvs 0.6.2 + THIS PORTION OF THE CODE IS BEING REVISED IN rvs 0.6.3 + + I have created two 'libraries' for use by rvs components. They + provide several functions that can be accessed by shell script by + using the code: + source "`rvs -d`/lib/stdio" + or + source "`rvs -d`/lib/rvsdb" + (`rvs -d' returns $$libdir$$) + stdio provides several functions for printing messages: + verbose MESSAGE + print MESSAGE to stdout only if $verbose is set to '-v' + out MESSAGE + print MESSAGE to stdout if $verbose isn't set to '-q' + warn MESSAGE + print "rvs: MESSAGE" to stderr + error MESSAGE + print "rvs: MESSAGE" and a quick message about `rvs --help' + (hinting at user error) to stderr, then exit with error + fatal MESSAGE + For internal error. Print "rvs: MESSAGE" to stderr and exit + with error + version + print the version information and exit with success + + rvsdb provides several functions and variables for dealing with the + rvs database: + getid FILE + returns what the id of a given file would be if it were in + the database. This is used to know where to put files when + commiting them. In 0.5.8-0.6.3 this is just the sha1sum of + the file + NOTE: the "log*" functions aren't very stable or developed + loginit FILE + initialize an rvs log at FILE. These logs are used for + metafiles, directory listings, and (probably) eventually + checkout logs + lograw LOG + prepare LOG for reading, and write the output to stdout (to + pipe into another function). This is mostly for internal + use by rvsdb + logread LOG VAR + read variable VAR from the logfile LOG + logwrite LOG VAR VAL + set variable VAR to VAL in the logfile LOG + logfind LOG VAL + return all the names of variables in logfile LOG who have + the value VAL + + the database (.rvs/*) + + So, what are all these files doing in this database? The scheme is + fairly simple. In the `.rvs' directory there is 1 directory, the + `files' directory. There used to be a folder for tempfiles (0.5.8- + 0.6.2), but no more (0.6.3+). If you need a tempfile, just run: + FILENAME=`tempfile` + The `files' directory is where all the data is kept. + + When any file is commited, whether it be a regular file, a + directory, a link, or any other type of file, 2 file are created in + `.rvs/files', the "raw-file" and the "meta-file". When we speek of + file IDs, we mean the filename of the corresponding file in + `.rvs/files' in rvs 0.5.8-0.6.3 this is just the sha1sum of the + file. The meta-file stores everything not part of the file itself; + the filename, file-type, author, copyright owner, file permissions, + timestamps, etc, and the ID of the corresponding raw-file. In the + case of an regular file, the raw-file contains the file itself. For + directories, it contains pointers to each file inside the + directory. + + $$libdir$$/commit calls $$libdir$$/commit.FILETYPE to generate the + raw-file, but generates the meta-file itself (in `.rvs/tmp', then + calls commit.f to commit the meta-file). It then returns the ID of + the meta-file. Therefore, the user never deals with the IDs of + raw-files, and doesn't need to. The metafiles contain pointers to + the corresponding raw-files. + + To keep things modular, commit.f is the ONLY thing that should + actually put files in `.rvs/files', and get.f the only thing that + should get them. Everything else should call them. + + The repo and init are the ONLY things that should have `.rvs' + hardcoded into them. If the repository directory is needed, then + use `rvs repo'. Again, in the core, these should only be the .f + functions, however, it will be useful to plugins. + + Why do we have the `files' directory, why don't we just put + everything in `.rvs'? This way: + * There is a spot to put user data, when we get around to writing + it + + + final thoughts + + I have set up bazaar repository at Launchpad: + https://launchpad.net/rvs + Only until rvs becomes self-hosting. + + If anyone needs any help, let me know, either via email, or via + Launchpad, I'll be happy to help/would love to have your help! + +~ Luke Shumaker <LukeShu@sbcglobal.net> +Happy Hacking! |