libfossil
High-level API Overview

The primary end goals of this project are to eventually cover the following feature areas:

  • Provide embeddable SCM to local apps using sqlite storage.
  • Provide a network layer on top of that for synchronization.
  • Provide apps on top of those to allow administration of repos.

To those ends, the fossil APIs cover the following categories of features:

Filesystem:

Databases (sqlite):

  • Opening/closing sqlite databases and running queries on them, independent of version control features. See fsl_db_open() and friends. The actual sqlite-level DB handle type is abstracted out of the public API, largely to simplify an eventual port from sqlite3 to sqlite4 or (hypothetically) to other storage back-ends (not gonna happen - too much work).
  • There are lots of utility functions for oft-used operations, e.g. fsl_config_get_int32() and friends to fetch settings from one of the three different configuration areas (global, repository, and checkout).
  • Pseudo-recusive transactions: fsl_db_transaction_begin() and fsl_db_transaction_end().
  • Cached statements (an optimization for oft-used queries): fsl_db_prepare_cached() and friends.

The DB API is (as Brad put so well) "very present" in the public API. While the core API provides access to the underlying repository data, it cannot begin to cover even a small portion of potential use cases. To that end, it exposes the DB API so that clients who want to custruct their own data can do so. It does require research into the underlying schemas, but gives applications the ability to do _anything_ with their repositories which the core API does not account for. Historically, the ability to create ad-hoc data structures as needed, in the form of SQL queries, has accounted for much of Fossil's feature flexibility.

Deltas:

  • Creation and application of raw deltas, using Fossil's delta format, independent of version control features. See fsl_delta_create() and friends. These are normally used only at the deepest internal levels of fossil, but the APIs are exposed so that clients can, if they wish, use them to deltify their own content independently of fossil's internally-applied deltification. Doing so is remarkably easy, but completely unnecessary for content which will be stored in a repo, as Fossil creates deltas as needed.

SCM:

  • A "context" type (fsl_cx) which manages a repository db and, optionally, a checkout db. Read-only operations on the DB are working and write functionality (adding repo content) is ongoing. See fsl_cx, fsl_cx_init(), and friends.
  • The fsl_deck class assists in parsing, creating, and outputing "artifacts" (manifests, control (tags), events, etc.). It gets its name from it being container for "a collection of cards" (which is what a Fossil artifact is).
  • fsl_content_get() expands a (possibly) deltified blob into its full form, and fsl_content_blob() can be used to fetch a raw blob (possibly a raw delta).
  • A number of routines exist for converting symbol names to RIDs (fsl_sym_to_rid()), UUIDs to RIDs (fsl_uuid_to_rid(), and similar commonly-needed lookups.

Input/Output:

  • The API defines several abstractions for i/o interfaces, e.g. fsl_input_f() and fsl_output_f(), which allow us to accept/emit data from/to arbitrary sources/destinations. A fsl_cx instance is configured with an output channel, the intention being that all clients of that context should generate any output through that channel, so that all compatible apps can cooperate more easily in terms of i/o. For example, the th1ish script binding for libfossil routes fsl_output() through the script's i/o channels, so that any output generated by libfossil-using code it links to can take advantage of the script-side output features (such as output buffering, which is needed for any non-trivial CGI output).

Utilities:

  • fsl_buffer, a generic buffer class, is used heavily by the library. See fsl_buffer and friends.
  • fsl_appendf() provides printf()-like functionality, but sends its output to a callback function (optionally stateful), making it the one-stop-shop for string formatting within the library.
  • The fsl_error class is used to propagate error information between the libraries various levels and the client.
  • The fsl_list class acts as a generic container-of-pointers, and the API provides several convenience routines for managing them, traversing them, and cleaning them up.
  • Hashing: there are a number of routines for calculating SHA1 and MD5 hashes. See fsl_sha1_cx, fsl_md5_cx, and friends. We haven't yet had need of an actual hash table class.
  • zlib compression is used for storing artifacts. See fsl_data_is_compressed(), fsl_buffer_compress(), and friends.