Configuring the Unison Codebase Manager

This document details how to create a.unisonConfigfile to store Unison Codebase Manager (UCM) configuration, as well as what UCM looks for in that file.

Where does Unison look for configuration?

When starting up, the Codebase Manager looks for a file named.unisonConfigin the same directory as your codebase. For example, if your codebase lives at~/.unison(which is the default codebase location), UCM will expect the configuration file to be~/.unisonConfig.

UCM loads the configuration on startup, but also watches the file for changes. If you edit the file and save it, UCM will reload the.unisonConfigfile and continue with the new configuration.

What is the configuration file format?

The.unisonConfigfile uses theData.Configuratorfile format.This is a temporary solution, and it's highly likely that the format will change in a future version of Unison.

What follows is an example configuration file. We'll explain the details of what this means below. Note that this is just an example and the values shown here will not actually work. Your file's basic structure will look similar to this if you are following therecommendations on how to organize your Unison namespace.

Currently You can host Unison code by usingUnison Share,Unison's native code-hosting platform, or by using GitHub.

# The Remote Mapping config block sets up default push and pull
# namespaces for integrating with Unison Share. The left side
# of the configuration block represents your local codebase and
# the right side of the equals sign is the mapping to the
# hosted namespace

RemoteMapping {

 # On Unison Share, your Unison code is hosted under your user name
 # in a namespace called "public". Currently everything hosted
 # under "public" is visible. Calling ''push'' within your
 # ''.> public'' namespace here will push all the code in that
 # namespace to Unison Share.
 public = "myUser.public"

 # Say you maintain a library that you'd like to host publically,
 # this configures a local namespace to push and pull from the
 # "main" remote branch.
 public.myLibrary = "myUser.public.myLibrary.main"

 # We support projects that are still hosted using git, with the
 # following url conventions:
 json = "git(git@github.com:myuser/json.git)"  # '.git' is optional!
 project1 = "git(git@github.com:myorg/coolproject)"

 # Some projects I occasionally make PRs against.
 # Example: from UCM, ''.prs.base> pull'' will get latest trunk
 prs.base = "unison.public.base.main"
 prs.distributed = "unison.public.distributed.main"

 # Another example with a nested namespace.
 http.client = "myUser.public.http.client"

}

# Attach myself as author and use BSD license.
DefaultMetadata = [ ".project1.trunk.metadata.authors.myself"
                  , ".project1.trunk.metadata.licenses.myself_bsd3_2020" ]

# If I needed to pick a different license for a sub-namespace
# I'd remove license from the root and add a license here instead
# DefaultMetadata {
#  project1 = [".project1.trunk.metadata.licenses.myself_bsd3_2020"]
#  org.example.foo = [".project1.trunk.metadata.licenses.myself_apache2_2020"]
# }

Your file will look similar to this if you are following therecommendations on how to organize your Unison namespace.

Configuring a default push/pull URL for a namespace

When working on a project in Unison, you'll often want topushyour work to a shared repository andpullcode from the repository into your codebase. To do so, you can use UCM'spushandpull.These commands take a Unison Share namespace path or aGit URL.Since the URL you'll want to push to or pull from generally remains constant for a given Unison namespace, the.unisonConfigfile allows you to set aRemoteMappingper namespace.

For example, while you can always supply an explicit argument topull,like so:

.project1> pull myUser.public.project1

… to avoid having to type or paste the URL every time, you could instead add the following to your.unisonConfig:

RemoteMapping.project1 = "myUser.public.project1"

Then you can simply issue apullfrom UCM while sitting in theproject1namespace:

.project1> pull

If you have multiple configuration settings that have the same prefix, you can collect them into a "configuration group." For example, the next two configurations have the same meaning:

RemoteMapping.project1 = "myUser.public.project1"
RemoteMapping.foo.bar = "myUser.public.foo.bar"


RemoteMapping {
  project1 = "myUser.public.project1"
  foo.bar = "myUser.public.foo.bar"
}

Configuration groups can be nested as well:

RemoteMapping {
      project1 = "myUser.public.project1"
      foo {
        bar = "myUser.public.foo.bar"
      }
    }

If both a Unison-share namespace and a Git url config block are present for the same local namespace, the UCM will prioritize Unison Share for code hosting.

Setting default metadata like License and Author

UCM allows you to "link" metadata to Unison definitions. These metadata are things likedocumentation,authors, as well as license and copyright information.

Usually you'll want to link yourself as the author of any code you write, and if you intend to publish that code for others to use, you'll want to specify a license laying out the conditions under which others may use your code.

The UCM has a special command,create.author,to help you construct some basic authorship information for use in the Unison ecosystem.

.project1> create.author aliceCoder "Alice Coder"

This adds the following values to your codebase:

1. metadata.authors.aliceCoder          : base.Author
2. metadata.authors.aliceCoder.guid     : GUID
3. metadata.copyrightHolders.aliceCoder : CopyrightHolder

Then, create a license under which to publish your code. The license is an ordinary Unison value of typemetadata.License:

metadata.licenses.aliceCoder2022 =
   License [copyrightHolders.aliceCoder] [Year 2022] licenseTypes.bsd3

Add that to your codebase:

.project1> add

(Though not strictly necessary, you can also alias these values to other projects where you are contributing, just using thealias.termorcopycommand.)

Now add the following to your.unisonConfigfile to make those values the default for any code you write:

DefaultMetadata = [ ".project1.metadata.authors.aliceCoder"
                   , ".project1.metadata.licenses.aliceCoder2020" ]

With this configuration, UCM will link these two values in to any Unison definitions you add to your codebase.

You might want to license different projects differently. In that case you should create a configuration value for your author under theDefaultMetadataconfiguration group, but rather than having a global license, just have a license per project:

DefaultMetadata = [".project1.metadata.authors.aliceCoder"]

    DefaultMetadata {
      project1 = [".project1.main.metadata.licenses.aliceCoder_bsd3_2020"]
      httpclient = [".project1.main.metadata.licenses.aliceCoder_bsd3_2020"]
      org.example.foo = [".project1.main.metadata.licenses.aliceCoder_apache2_2020"]
    }

With this configuration, UCM will link thealiceCoder_apache2_2020license to any definitions you add to theorg.example.mylibrarynamespace and any subnamespaces and will usealiceCoder_bsd3_2020when inproject1orhttpclientnamespaces.