bantorra: Library Management

Introduction

A library in the bantorra framework is a tree of units that can be accessed via unit paths from the root. A unit path is a list of strings, such as lib/num/types. The purpose of the bantorra framework is to provide a flexible mechanism to map each unit path to some underlying file path. For example, the unit path lib/num/types might be mapped to the file path /usr/lib/cool/number/types.data, and the resolution process takes in both what is set up by the application and what is provided by its users.

In the simplest case, there is a one-to-one correspondence between units and files under a directory: the unit path a/b/c corresponds to the file a/b/c.data where .data is the extension specified by the application. The root directory is marked by a special file called anchor, which is a file with a fixed name again specified by the application. For example, the existence of a dune file means there is an OCaml library in the eyes of the dune building tool. An anchor in the bantorra framework marks the root of a library. If the anchor file name is anchor.json, the file at /usr/lib/cool/number/anchor.json indicates that there is a library containing files under /usr/lib/cool/number.

It is common for units within a library to access units in another library. To do so, an anchor file may mount another library in the tree, in a way similar to how partitions are mounted in POSIX-compliant systems. Here is a sample anchor file:

{
  "format": "1.0.0",
  "mounts": {
    "lib/num": ["local", "/usr/lib/cool/number"]
  }
}

The above anchor file presumably mounts the library number at lib/num. With this, the unit path lib/num/types will be routed to the unit types within the library number. The resolution is recursive because the mounted library may mount yet another library. The JSON array ["local", "/usr/lib/cool/number"] specifies where the location of the library, and the application has full control of how to interpret the location specification ["local", "/usr/lib/cool/number"]. The example assumes that ["local", path] refers to path in a local file system, but the application can choose to use any OCaml function from JSON data to directory paths. A few basic routing functions are provided in Bantorra.Router.

Anchors

As mentioned earlier, an anchor file looks like this:

{
  "format": ...version of the anchor format...,
  "mounts": {
    "path/to/lib1": ...(spec of lib1)...
    "path/to/lib2": ...(spec of lib2)...
    ...
    "path/to/libn": ...(spec of libn)...
  }
}

The format version string is decided by the application; it can help detect outdated anchor files. As for the mounts property, if it is missing, then the library has no dependencies. Each dependency is specified by a key/value pair, where the key is the mount point and value is the parameter for locating the library. During the resolution, the entire parameter is passed to the router. See Bantorra.Router.t and Bantorra.Router.param. The order of entries in mounts does not matter because the dispatching is based on longest prefix match. If no match can be found, then it means the unit path refers to a local unit. The same library can be mounted at multiple points. However, to keep the resolution unambiguous, there cannot be two libraries mounted at the same point. Here is an example demonstrating the longest prefix match:

{
  "format": "1.0.0",
  "mounts": {
    "lib": "stdlib",
    "lib/bantorra": ["git", {url: "https://github.com/RedPRL/bantorra"}]
  }
}

The unit path lib/orntorra will be routed to the unit orntorra within the stdlib library, pending further resolution (as the stdlib library might further mount other libraries), while the unit path lib/bantorra/shisho will be routed to the git repo https://github.com/RedPRL/bantorra, not the unit bantorra/shisho in the stdlib library, because lib/bantorra matches lib/bantorra/shisho better than lib does.

Note that, if some library is mounted at world/towitorra, then the original local unit with the unit path world/towitorra will no longer be accessible. As an analogy using the POSIX-compliant mount, the original files within /mnt will not be accessible after mounting a file system at /mnt.