A CLI and OCaml library for managing contacts

metadata

+273 -26
+17 -1
.gitignore
··· 1 - _build 1 + # OCaml build artifacts 2 + _build/ 3 + *.install 4 + *.merlin 5 + 6 + # Third-party sources (fetch locally with opam source) 7 + third_party/ 8 + 9 + # Editor and OS files 10 + .DS_Store 11 + *.swp 12 + *~ 13 + .vscode/ 14 + .idea/ 15 + 16 + # Opam local switch 17 + _opam/
+1
.ocamlformat
··· 1 + version=0.28.1
+53
.tangled/workflows/build.yml
··· 1 + when: 2 + - event: ["push", "pull_request"] 3 + branch: ["main"] 4 + 5 + engine: nixery 6 + 7 + dependencies: 8 + nixpkgs: 9 + - shell 10 + - stdenv 11 + - findutils 12 + - binutils 13 + - libunwind 14 + - ncurses 15 + - opam 16 + - git 17 + - gawk 18 + - gnupatch 19 + - gnum4 20 + - gnumake 21 + - gnutar 22 + - gnused 23 + - gnugrep 24 + - diffutils 25 + - gzip 26 + - bzip2 27 + - gcc 28 + - ocaml 29 + - pkg-config 30 + 31 + steps: 32 + - name: opam 33 + command: | 34 + opam init --disable-sandboxing -a -y 35 + - name: repo 36 + command: | 37 + opam repo add aoah https://tangled.org/anil.recoil.org/aoah-opam-repo.git 38 + - name: switch 39 + command: | 40 + opam install . --confirm-level=unsafe-yes --deps-only 41 + - name: build 42 + command: | 43 + opam exec -- dune build -p sortal 44 + - name: switch-test 45 + command: | 46 + opam install . --confirm-level=unsafe-yes --deps-only --with-test 47 + - name: test 48 + command: | 49 + opam exec -- dune runtest --verbose 50 + - name: doc 51 + command: | 52 + opam install -y odoc 53 + opam exec -- dune build @doc
+15
LICENSE.md
··· 1 + ISC License 2 + 3 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org> 4 + 5 + Permission to use, copy, modify, and distribute this software for any 6 + purpose with or without fee is hereby granted, provided that the above 7 + copyright notice and this permission notice appear in all copies. 8 + 9 + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+4
README.md
··· 164 164 ## Project Status 165 165 166 166 Still very much just used by Anil Madhavapeddy. You're welcome to try it, but let me know... 167 + 168 + ## License 169 + 170 + ISC License - see [LICENSE.md](LICENSE.md) for details.
+11 -11
bin/dune
··· 2 2 (name sortal_cli) 3 3 (public_name sortal) 4 4 (libraries 5 - sortal 6 - sortal.schema 7 - eio 8 - eio_main 9 - xdge 10 - cmdliner 11 - logs 12 - logs.cli 13 - logs.fmt 14 - fmt 15 - fmt.tty)) 5 + sortal 6 + sortal.schema 7 + eio 8 + eio_main 9 + xdge 10 + cmdliner 11 + logs 12 + logs.cli 13 + logs.fmt 14 + fmt 15 + fmt.tty))
+5
bin/sortal_cli.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 open Cmdliner 2 7 3 8 (* Main command *)
+5
dune
··· 1 + ; Root dune file 2 + 3 + ; Ignore third_party directory (for fetched dependency sources) 4 + 5 + (data_only_dirs third_party)
+12 -1
dune-project
··· 2 2 3 3 (name sortal) 4 4 5 + (generate_opam_files true) 6 + 7 + (license ISC) 8 + (authors "Anil Madhavapeddy") 9 + (homepage "https://tangled.org/@anil.recoil.org/sortal") 10 + (maintainers "Anil Madhavapeddy <anil@recoil.org>") 11 + (bug_reports "https://tangled.org/@anil.recoil.org/sortal/issues") 12 + (maintenance_intent "(latest)") 13 + 5 14 (package 6 15 (name sortal) 7 16 (synopsis "Contact metadata management with XDG storage and versioned schemas") ··· 23 32 bytesrw 24 33 fmt 25 34 cmdliner 26 - logs)) 35 + logs 36 + (odoc :with-doc) 37 + (alcotest (and :with-test (>= 1.7.0)))))
+13 -13
lib/core/dune
··· 2 2 (public_name sortal) 3 3 (name sortal) 4 4 (libraries 5 - sortal.schema 6 - eio 7 - eio.core 8 - eio_main 9 - xdge 10 - jsont 11 - jsont.bytesrw 12 - yamlt 13 - bytesrw 14 - fmt 15 - cmdliner 16 - logs 17 - str)) 5 + sortal.schema 6 + eio 7 + eio.core 8 + eio_main 9 + xdge 10 + jsont 11 + jsont.bytesrw 12 + yamlt 13 + bytesrw 14 + fmt 15 + cmdliner 16 + logs 17 + str))
+5
lib/core/sortal.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 module Temporal = Sortal_schema.Temporal 2 7 module Feed = Sortal_schema.Feed 3 8 module Contact = Sortal_schema.Contact
+5
lib/core/sortal.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Sortal - Username to metadata mapping with XDG storage 2 7 3 8 This library provides a system for mapping usernames to various metadata
+5
lib/core/sortal_cmd.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 open Cmdliner 2 7 3 8 module Contact = Sortal_schema.Contact
+5
lib/core/sortal_cmd.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Cmdliner terms and commands for contact management. 2 7 3 8 This module provides ready-to-use Cmdliner terms for building
+5
lib/core/sortal_git_store.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 module Contact = Sortal_schema.Contact 2 7 3 8 type t = {
+5
lib/core/sortal_git_store.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Git-backed contact store with automatic version control. 2 7 3 8 This module wraps {!Sortal_store} to provide automatic git versioning
+5
lib/core/sortal_store.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 module Contact = Sortal_schema.Contact 2 7 module Temporal = Sortal_schema.Temporal 3 8
+5
lib/core/sortal_store.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Contact store with XDG-compliant storage. 2 7 3 8 The contact store manages reading and writing contact metadata
+5
lib/schema/sortal_schema.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 module V1 = struct 2 7 module Temporal = Sortal_schema_temporal 3 8 module Feed = Sortal_schema_feed
+5
lib/schema/sortal_schema.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Sortal Schema - Versioned data types and serialization 2 7 3 8 This library provides versioned schema definitions for contact metadata
+5
lib/schema/sortal_schema_contact_v1.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 let version = 1 2 7 3 8 type contact_kind = Person | Organization | Group | Role
+5
lib/schema/sortal_schema_contact_v1.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Contact schema V1 with temporal support. 2 7 3 8 This module defines the V1 contact schema with support for time-bounded
+5
lib/schema/sortal_schema_feed.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 type feed_type = 2 7 | Atom 3 8 | Rss
+5
lib/schema/sortal_schema_feed.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Feed subscription with type and URL. 2 7 3 8 A feed represents a subscription to a content source (Atom, RSS, or JSONFeed). *)
+5
lib/schema/sortal_schema_temporal.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 type date = Ptime.date 2 7 3 8 type range = {
+5
lib/schema/sortal_schema_temporal.mli
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Temporal validity support for contact fields. 2 7 3 8 This module provides types and functions for managing time-bounded
+47
sortal.opam
··· 1 + # This file is generated by dune, edit dune-project instead 2 + opam-version: "2.0" 3 + synopsis: 4 + "Contact metadata management with XDG storage and versioned schemas" 5 + description: """ 6 + Sortal provides contact metadata management with versioned schemas, 7 + XDG-compliant storage, git versioning, and CLI tools. 8 + 9 + The library is split into two components: 10 + - sortal.schema: Versioned data types with minimal dependencies 11 + - sortal: Core library with storage, git integration, and CLI support""" 12 + maintainer: ["Anil Madhavapeddy <anil@recoil.org>"] 13 + authors: ["Anil Madhavapeddy"] 14 + license: "ISC" 15 + homepage: "https://tangled.org/@anil.recoil.org/sortal" 16 + bug-reports: "https://tangled.org/@anil.recoil.org/sortal/issues" 17 + depends: [ 18 + "dune" {>= "3.20"} 19 + "ocaml" {>= "5.1.0"} 20 + "eio" 21 + "eio_main" 22 + "xdge" 23 + "jsont" 24 + "ptime" 25 + "yamlt" 26 + "bytesrw" 27 + "fmt" 28 + "cmdliner" 29 + "logs" 30 + "odoc" {with-doc} 31 + "alcotest" {with-test & >= "1.7.0"} 32 + ] 33 + build: [ 34 + ["dune" "subst"] {dev} 35 + [ 36 + "dune" 37 + "build" 38 + "-p" 39 + name 40 + "-j" 41 + jobs 42 + "@install" 43 + "@runtest" {with-test} 44 + "@doc" {with-doc} 45 + ] 46 + ] 47 + x-maintenance-intent: ["(latest)"]
+5
test/test_schema.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Schema-only tests (no I/O dependencies) *) 2 7 3 8 let test_temporal () =
+5
test/test_sortal.ml
··· 1 + (*--------------------------------------------------------------------------- 2 + Copyright (c) 2025 Anil Madhavapeddy <anil@recoil.org>. All rights reserved. 3 + SPDX-License-Identifier: ISC 4 + ---------------------------------------------------------------------------*) 5 + 1 6 (** Tests for the Sortal library *) 2 7 3 8 open Eio.Std