FSC(1) FSC(1) FSC fsc - personal source control utility SYNOPSIS fsc [ moduleName ... ] [options] DESCRIPTION Fsc is a source control utility which keeps track of the successive versions of one or more files. Using this program, you can remember all of your changes to your files, and get back any of the old versions of the files. The versions of the files can be given names so that you can easily extract sets of files which were consistent with each other at some point in time. Fsc does not perform any locking of files, and for this reason it is most useful as a personal source control utility. It provides a simple way to make backups of changes to files you are editing without you having to worry about read-only verses write-enabled files, or having to remember to check-out files before you edit them. Fsc only can only be used for text files. Binary files cannot be used since null characters will prematurely terminate input lines. Because some of the options of fsc accept a variable number of arguments, module names cannot be specified immediately after these options. In order to avoid any confusion, it is best to always specify module names first, followed by the options for the command. MODULES Fsc manipulates entities called modules. A module is simply the name of a text file that you are interested in keeping versions of. For example, a source file "doit.c" is a module, and so is a documentation file "howto.txt". The module name includes the suffix of the file (as in the above examples). A module name can also include leading directory components, as in "src/bar.c". The use of absolute module names (those starting with a slash) is not recommended since the absoluteness of the path is not preserved by fsc. Modules are stored in a directory called the module storage directory. The default module storage directory is "FSC_EDITS" in your current directory. This default is convenient when you are in a directory containing many modules, and you want a local storage directory to contain just those modules. If you give the -p option, then you can locate the storage directory anywhere you choose. This is useful if you choose to have a common storage directory for all of your files, independent of where they actually are used. The term module is used here instead of file because while they can usually be considered as the same thing, there can be differences. - 1 - Formatted: November 14, 2024 FSC(1) FSC(1) The module name is the string used by fsc to refer to the whole set of versions of a file stored in the storage module directory. Using the appropriate options, it is possible to insert the contents of an arbitrary file as a version of a module, or to extract a version of a module into an arbitrary file. Only by default does the file name to be inserted or extracted match the module name. CREATING MODULES To use fsc for the first time, you need to create your storage directory. Therefore, cd to the directory where you want it to be, which is probably the directory containing the modules you want to save the versions of. Then create the directory "FSC_EDITS". To start using a module under fsc, you must first use the -create option. This creates the initial edit for that module in the storage directory, with the contents of the specified module as the initial edit. Thus, if you have a source file "prog.c", then the command: fsc prog.c -create creates the initial edit of the module. You can then delete the file "prog.c" if desired and fsc would be able to recreate it later. Alternatively, you can leave it there as the working copy of the module. UPDATING MODULES To save another version of the module, you use the -u option. This updates the files in the storage directory to include the latest changes. Thus, to continue the example, after editing "prog.c", the command: fsc prog.c -u will save the changes as a new edit. This command compares the newest version of the module to the previous version, and saves the new version and the differences in the module storage directory. At this point, you can once again delete the "prog.c" file if desired, and later get back either of the two versions of the program. In either the -create or -u options, the file containing the new version of the module defaults to the same name as the module. In the example, the module "prog.c" was created and updated from the data in the file "prog.c". When you wish the data to come from some other file, you can use the -i option, which specifies the input file to use for the data. For example, if you wanted to update "prog.c", but from a filename called "newprog.c", then the command: fsc prog.c -u -i newprog.c would save a new version of "prog.c", but with the data that was in - 2 - Formatted: November 14, 2024 FSC(1) FSC(1) the file "newprog.c". In this case, the file "prog.c" does not have to exist, and isn't referenced even if it did exist. Again, once the update is complete, you could delete "newprog.c" if desired and then later you can retrieve its contents. The -i option can also be a directory name, in which case the input file is contained in the specified directory having the same name as the module name. The -cu option conditionally updates a module. That is, it will only do an update if there are any differences between a file and the latest version of a module. This is convenient when related changes are made to many modules in a directory, and one command using wild- cards or the -all option can update just those modules that were changed. The -du option combines the effects of the -d and -u options. It displays the differences between a file and the latest version of a module. If there are any differences, it then proceeds to perform an update of the module with that file, possibly asking for remarks. This option is very useful when used with wild-carded module names and the -r option. Then you can update just those modules which were changed by an edit session, and see the changes for each module before typing the appropriate remark for each module. EXTRACTING A VERSION OF A MODULE To extract a previous version of a module, you specify the name of the module and use the -e option to specify the edit number you want extracted. Edit numbers are assigned sequentially starting with 1. Thus the initial version of the module has edit number 1, the first version has edit number 2, and so on until the latest version. If the -e option is not used, or if no edit number is supplied for it, then the latest edit number is extracted. Therefore, this is the default action if no options at all are specified. Edit numbers can also be zero, negative, or be a name with an optional offset. The number zero represents the latest edit number, and negative numbers indicate edit numbers backwards from the latest edit number. Edit names represent edit numbers whose name had been set by using the -name option. For example, if edit number 10 was associated with the name "foo", then the edit name "foo" represents 10, "foo-4" represents 6, and "foo+2" represents 12. The special reserved names "oldest" and "newest" refer to the oldest and newest versions of the module in the edit history. As an example of extractions, assume that you have saved ten versions of the module "prog.c". The following commands will then extract the versions of the file with the specified edit numbers: fsc prog.c ;version 10 (the latest) fsc prog.c -e 9 ;version 9 (the version just prior) - 3 - Formatted: November 14, 2024 FSC(1) FSC(1) fsc prog.c -e oldest ;version 1 (the oldest version) fsc prog.c -e -2 ;version 8 (latest version - 2). The output filename is again defaulted to the module name. So when the module "prog.c" is extracted, the specified version of the module is written to the file "prog.c". You can change the output filename using the -o option. Thus, the command: fsc prog.c -o newprog.c will extract the latest version of the module "prog.c", and put it into the file "newprog.c". Once again, the file "prog.c" is ignored, whether or not it existed. A directory name can be used for the -o option, in which case the output file will be placed in the specified directory with the same name as the module name. In order to prevent accidental overwriting of a file, fsc will by default ask you if overwriting is permitted if that would occur. A common mistake might be to edit "prog.c", and then try to update the module, but forget to specify the -u option. Then fsc would try to extract the newest version of the module, and thus overwrite the file with the new changes. Asking the question allows you to notice your mistake, and prevent the overwriting. The -fw option will force overwriting of the file, thus never asking you if overwriting is permitted. This might be useful in a script, or when you are SURE that you want to overwrite any existing file. The -nw option is the no-overwrite option, and will cause any existing files to NOT be overwritten, again without asking you. This is useful if you already have some of the modules in your directory, and you want to extract the rest of the modules without overwriting the ones you already have. Specifying both -fw and -nw is an error. The -t option is used to output an extracted module to the terminal (stdout), instead of writing it to a file. This is useful in order to view the beginning of a version of the file. This can be interrupted if you do not want to see the whole file. ASSIGNING EDIT NAMES FOR A VERSION The -name option is used to associate a name for the newest version of a module. It can be given along with the -create, -u, -cu, or -du options, to specify a name for the new version of the module. It can also be given by itself in order to specify a name for the newest version of a module. Each edit number can have many names associated with it, so this will not remove any previously defined name for the edit. This option is useful to correlate many modules together. For example, when a new version of a program is ready to be released, you could give each - 4 - Formatted: November 14, 2024 FSC(1) FSC(1) module of the program the same name "release1". Then in the future, you can recreate the sources making up that release by extracting the edits with the name "release1" for every module. Edit names must contain at least one non-digit character, and must contain at least one non-digit character following the last plus or minus sign in the name. These rules prevent ambiguous parsing of edit numbers for the -e, -t, -d, and -l options. DISPLAYING DIFFERENCES BETWEEN VERSIONS The -d option is used to display the differences between two versions of a module, or a file and a version of a module. There are three modes for this action, depending on how many edit numbers are supplied. These modes are illustrated by the following examples: fsc foo.c -d Compare latest version against "foo.c" fsc foo.c -d 3 Compare version 3 against "foo.c" fsc foo.c -d 3 4 Compare version 3 against version 4 This option accepts the -i option to specify the file to be compared. When using the -d option, the output defaults to stdout. Therefore, you must use -o (or redirection) if you wish the differences saved to a file. Using -q with -d will only output a quick summary of the changes, instead of the detailed changes. This summary only supplies the number of lines inserted, deleted, and unchanged between the files. Using -w with -d will display all of both files, showing in detail what the differences are using change bars. The -d option may need to write one or two temporary files in order to extract old versions of a module to be compared. They are deleted again just before differences are output, so that stopping the output before it is complete will not leave these files around. The temporary files are usually written to the /tmp directory. If this is not possible because of permission or disk full problems, then you can specify the directory for writing the temporary files into. This is done by defining the "TMPDIR" environment variable to be the path of the directory. SPECIFYING MULTIPLE MODULES More than one module can be acted on by a single fsc command. The effect is as if each module was acted on using separate invocations of fsc. Multiple modules can be specified in one of three methods. These are to explicitly specify a list of module names on the command line, to act on every module in the module storage directory by using -all, or to act on a list of module names read from standard input using -stdin. Only one of these methods can be used in one command. The -all option can be used with any of the action options. It means perform the operation for all modules in the module storage directory. Subdirectories within the module storage directory are also scanned. - 5 - Formatted: November 14, 2024 FSC(1) FSC(1) The -stdin option is used to read module names from standard input. Module names are read one per line and operated on until end of file is reached. Blank lines are ignored. This option is useful in conjunction with find to operate on all of the modules within a directory hierarchy. When -stdin is used, confirmation for overwriting of files is not possible, and so one of the -fw or -nw options must also be specified. If -all or -input are not specified then you can specify multiple module names on the command line, and the actions will be performed with those modules. When using multiple explicit modules, the -all option, or the -stdin option, the -i and the -o options have a slightly different meaning. In these cases, the -i and -o arguments must be directory names which contains filenames with the same name as the module names. If the argument is not a directory, then an error is given. This feature is used for example, to extract all the modules and place them into some remote directory, as in: fsc -all -e -o tempdir You should be careful when specifying numeric edit numbers for multiple modules. Most probably, a particular edit number is not appropriate for multiple modules, since changes to two files corresponding to a particular edit number are not usually related. Using edit names avoids these problems. As an example, if you wanted to extract every module which had an edit that was named "rev3", then you could use the command: fsc -all -e rev3 Some other useful examples of commands which use multiple modules are: fsc *.c -create fsc -check fsc -cu -all fsc -clean -all fsc -all -name release2 ENTERING REMARKS FOR AN EDIT Whenever a module is created or updated, you can optionally ask to include some remarks describing why that edit was created which will be saved in the edit history. The remarks consist of one or more lines of text. Remarks are saved only when the -r option is used as part of the command. If the -r option is followed by an argument, then the argument is a filename which contains the remarks for the update. This is useful if you are updating many modules at once, and want the same remarks for each module. - 6 - Formatted: November 14, 2024 FSC(1) FSC(1) If no argument follows the -r option, then the remarks are entered from the terminal. Fsc prompts you for each line of the remarks. When you have entered all of the lines of the remarks, a single blank line is used to terminate the input. Some simple editing commands can be used while entering remarks. This commands are used at the beginning of a line, and start with an exclaimation mark. The following commands are available: !b Backs up to the previous line so that you can retype it. !c Clears all of the remarks entered so far so that you can reenter them. !r Redisplays all of the remarks entered so far. !q Aborts updating of the current module. As an example of using remarks, to update "prog.c" and supply some remarks for the update from the terminal, you can use the command: fsc prog.c -u -r OTHER OPTIONS The -clean option is used to remove files which match the newest versions of modules. If a file exists which matches the newest version of a module, then the file is deleted, otherwise it is kept. This option is used to clean up a work directory after building a new version of a product. This option is especially useful when used with the -all option. It will also accept the -i option to specify a directory containing the files to be cleaned. The -check option is used to find out if a file does not match the latest version of a module. If so, a message is given. If the file does match, no output occurs. This option is thus useful to determine which files have been modified and in need of updating. The -all option is defaulted for this option, since it is usually used for all modules. For example, fsc -check will report on all files which are different than the latest modules. If -q is specified, then the output will consist of the module names with no other output. This is useful for the back-quote operator in shell commands for referencing the modules which are out of date. The -check option will also accept the -i option. The -l option prints a list of edits for the module, giving the user name, date, user remarks, and names specified for the edits. If no edit number is supplied, then all edits are printed in reverse order. If a single edit number is supplied, then only that edit number is - 7 - Formatted: November 14, 2024 FSC(1) FSC(1) printed. If two edit numbers are supplied, then all edits in the specified range are printed. The output from this option defaults to stdout. You can use the -o option to save the results to a file. The -prune option is used to permanently remove early edits from an edit history. This is useful if you wish to cut down on the amount of disk space taken by an edit history file, or when you want to start another release of a file, and want a copy of the edit history file for that new release. The option takes an edit number to preserve, and all edits in the edit history file before that edit are deleted, and can no longer be referenced. For example, to keep only the current edit plus the previous 10 edits of the module "file", you could use the command: fsc file -prune -10 Since the -prune option is unrecoverable (unless backup files are available), fsc asks the user to verify that the prune is really wanted. The -fu option can be used to bypass this verification. The -v option can be specified with any other action, and outputs status information about the progress of the action. This is useful for debugging of problems, or just for amusement when the system is slow or a large file is being processed. It accepts a numeric argument to indicate the verbosity for output. The levels are as follows: 0 No output at all (except for errors). 1 Single-line output describing action (default). 2 Detailed status as action proceeds. Finally, fsc has an -h option, which will briefly list the possible options. SPECIAL CHARACTER SEQUENCES When extracting a file, fsc looks for and updates special character sequences in the first few lines of the file. These special sequences are used for documentation purposes, such as describing the edit number the file is from. For speed of extraction and updating, these sequences are usually limited to the first 25 lines of the file, since fsc then does not have to examine each line of the file. The -m option can be used to change the number of lines to be modified from the default value of 25. Specifying zero totally disables the special character sequences, whereas specifying a very large number will cause the sequences to be checked for each line of the file (and thus slightly slow fsc down). Each special sequence is of the form: [# keyword value, keyword value, ..., keyword value #] - 8 - Formatted: November 14, 2024 FSC(1) FSC(1) where each keyword describes an item, and each value is the value for the preceding keyword. The keywords can be in upper or lower case, or both. The single space following the "[#", following each comma, and preceding the "#]" must be present. If the sequence is wrong, an unknown keyword is used, the line is longer than 200 characters, or more than four keywords are used, then the whole line will not be changed. The current keywords which can be used are the following: edit The edit number date The date that the edit was created user The user name who created the edit module The module name In order to use this special character sequence, you simply insert it into your module inside of a comment (within the first few lines). When this is done, the value parts of the sequence can be null. For example, if you want to put a special sequence into a program called "delete.c", then you could edit the first few lines as follows: /* * Delete - program to delete files * [# Edit, Date #] */ When an extract is done, the proper edit number and date are automatically inserted as the new values. Thus, if you extract edit 23 of the module "delete.c" which had been created on 8 January 2000, then the resulting file would begin: /* * Delete - program to delete files * [# Edit 23, Date 8-Jan-2000 #] */ When updating a module, it is never necessary to edit these sequences, as any old values will be removed and replaced with the new ones. Also, when using the -d or -du options, lines with these sequences compare as if the values were null, and thus will not cause spurious differences. During an update, the special character sequences are read and any edit value found is compared against the current edit number of the module. If they differ, then the update fails. This provides a simple interlock check for the case of two users extracting the same version of a file, editing it, and then both updating it without knowledge of each other. In this case, the second user would fail, and then he can merge his edits with the previous user's edit and then retry the update. This checking is disabled if there is no special character sequence containing the edit keyword, the edit number value is null, or if the -fu option is used to indicate that the check is - 9 - Formatted: November 14, 2024 FSC(1) FSC(1) not needed. MODULE STORAGE DIRECTORY DETAILS Each module in a storage directory is stored as two files in the directory. The two files have the same name as the module's file name except for the addition of a suffix. The file with the ".s" suffix is a copy of the latest version of the module, with one extra line at the beginning. The file with the ".e" suffix is the edit history of the module, and contains information needed to extract previous versions of the module. For module names which contain directory components, the directory paths are reflected in the structure of the module storage directory. For example, the module "src/bar.c" would be stored in the directory "FSC_EDITS/src" as the two files "bar.c.s" and "bar.c.e". Subdirectories in the module storage directory are automatically created when new modules require them. If the edit history for a module becomes corrupted (which hopefully should never happen), you will at least have the most recent version of the module. All you have to do is remove the first line from the file with the ".s" extension. The edit history file contains file offsets to lines in the lastest version of the module, along with lines of text that has been deleted from older versions of the module. If you modify the files in the module storage directory outside of the fsc program, you will probably corrupt your edit history, causing errors when you extract old versions of the module. One safe operation that you can do is to change the name of a module by renaming both the ".s" and ".e" files to the new module name (with the same suffixes). For example, the module "fred.c" can be changed to "barney.c" by renaming "fred.c.s" to "barney.c.s" and "fred.c.e" to "barney.c.e". You can also move the files within a module storage directory to a different subdirectory, which will change the directory component of the moved module names. ERROR HANDLING Fsc handles disk full problems during a create or update operation without any damage occurring to the edit history files. If an edit cannot be completed because of such problems, the edit is backed out completely, and you will get an error message about the disk problem. There is no need for any error recovery in this case, other than retrying the update when more disk space is available. Fsc also disables signals during the critical file operations, so you do not have to worry about damaging the edit history files because of attempts to quit out of the program. - 10 - Formatted: November 14, 2024 FSC(1) FSC(1) As an additional safeguard, the new latest version of a module does not overwrite the old version. The new version is written with a ".n" extension, the old version is then renamed to a ".o" extension, and only then is the ".n" extension renamed to the ".s" extension and the ".o" file deleted. In this way, a valid copy of the latest version of a module should always be present. FILES FSC_EDITS Default module storage directory file.s Latest edit of file file.e Edit history of file AUTHOR David I. Bell dbell@canb.auug.org.au - 11 - Formatted: November 14, 2024