This directory holds unpacked views of my git repos. The directory structure here mirrors the structure seen by the git daemon. NOTE: This is taken offline for maintenance occasionally, usually around 06:10-06:15 North American Eastern time (UTC-0400 in the Northern Hemisphere summer, UTC-0500 in the winter). When it is offline, the directory will contain nothing but this file. Most outages are expected to be short (less than a minute), but may sometimes be longer. The view presented here may lag what's seen by the git daemon, for various reasons, but the lag should not be over about 24 hours. Each repo's directory contains numerous things. In this description, a `commit link' is a symlink pointing to a commit directory under the commit/ directory; a `commit file' is a file containing the commit ID, with the two-character grouping directory prepended so it's a valid path relative to the commit/ directory. Commit files and HEAD-file always have a newline appended to the relevant content. - A subdirectory branch-link/, which contains one symlink per branch, a commit link for that branch's head commit. - A subdirectory branch-file/, which is just like branch-link/ except that it holds commit files instead of commit links. - A subdirectory tag-link/, which is like branch-link/ but for tags rather than branches. (I don't use tags much, so this is empty for many of my repos.) - A subdirectory tag-file/, which is just like tag-link/ except that it holds commit files instead of commit links. - A symlink HEAD-link which is either a commit link for HEAD (if the repo is in detached-HEAD state) or a symlink to a branch link in the branch-link/ directory (if HEAD is on a branch). - A file HEAD-file which contains either the word "commit", a single space, and a commit path for HEAD relative to the commit/ directory (if the repo is in detached-HEAD state) or the word "branch", a single space, and the branch name (if HEAD is on a branch). (In the detached-HEAD case, this is not a commit file, but only because of the "commit"-and-space prefix.) - A directory commit/ which contains commits. Commits are grouped into subdirectories based on the first two characters of their commit hashes. Each commit has a directory containing info about that commit: - A file message which contains the commit message. - A file time-raw which contains the commit timestamp, as an ASCII decimal integer in seconds past the UNIX epoch. - A file time-utc which contains the commit timestamp, formatted as YYYY-MM-DD hh:mm:ss in UTC. - A file author which contains the name and email specified for the commit's author. - A file encoding, which may or may not be present. If the commit declared an encoding for the commit message, this file is present and contains the encoding string; if not, this file is absent. (The way git is defined, an absent encoding means the message is to be interpreted as UTF-8. I think this is a botch, but they didn't ask me.) - A directory parents-link/ which contains zero or more symlinks, named 1, 2, etc, as many in all as the commit has parents. These are commit links for the parent commits. (A root commit, with no parents, still has a parents-link/ directory, but it's empty.) - A directory parents-file/ which is just like parents-link/ except that it holds commit files instead of commit links. - A directory tree/ which contains the unpacked working tree corresponding to the commit in question. Directories and symlinks are always mode 555; plain files appear with the modes they have in the repo (usually 644 or 755). - A file abbrev which contains the commit's hash, abbreviated as far as it can be and still remain unambiguous. - A directory diff/ which is unlistable. If you ask for a name which consists of two (possibly abbreviated) commit IDs with a dash between them, you'll get a file whose contents are git diff output between those two commits (if the name is COMMIT1-COMMIT2, then the file contains the output of "git diff COMMIT1 COMMIT2"). If the name doesn't match that syntax (no dashes, multiple dashes, or things other than 1-40 hex characters on either side of the dash), or if either commit ID is ambiguous or doesn't match any commits, the corresponding file doesn't exist. You can abbreviate the commit IDs as far as is unambiguous, even if that's all the way down to one character. - A directory abbrev-link which is unlistable; if you ask for a name which is an unambiguous commit ID abbreviation, you will get a commit link for that commit. - A directory abbrev-file which is unlistable. If you ask for a name which is an unambiguous commit ID abbreviation, you will get a commit file for that commit. If you ask for a name which is an ambiguous commit ID abbreviation - one which is an abbreviation of more than one commit hash - you will get a file containing "ambiguous\n". If you ask for a name which could be a commit ID (1-40 lowercase hex characters) but which matches no actual commits in that repo, you will get a file containing "no match\n". If you ask for anything else, it doesn't exist. The software responsible for this presentation of git repos as a filesystem is all publicly available, in various git repos. It is made up of three major pieces: gitfs, libqfs, and libfstree. The easiest place to start explaining this is probably libqfs. This is a library that is a quasi-filesystem access protocol. Client software can use libqfs to access a filesystem tree backed by a daemon; the daemon uses libqfs to provide access to data, which it can get from wherever that particular backend implementation finds appropriate. libfstree is, loosely put, a userland filesystem framework: it handles path walks, symlink following, and mount points. A mount point can be backended by anything that supports a small handful of calls. libfstree includes a backend that gets its data from the local filesystem; it includes another backend that uses libqfs's client-side interface. The third piece is gitfs, which is the hard part; it is a libqfs backend server which presents git repos as a filesystem over libqfs. The only part needed besides those three pieces is code in my FTP and HTTP servers to use libfstree for the data they present to the world, with most of it coming from the local-filesystem backend, backed by my exported-data subtree, with the unpacked-git-repos stuff backed by the libqfs backend, talking to gitfs. All five of these pieces (libqfs, gitfs, libfstree, the FTP server, and the HTTP server) are available as git repos, either clonable by the world or fetchable in their unpacked form here. For example, gitfs is in a repo available as gitfs/ here (sibling to this file) or as git://git.rodents-montreal.org/gitfs for git clone. Latest update (2024-02-24): The HTTP server code has been live for over a week now. Today I got the FTP server code working enough that I've put it into production; we'll see how it goes.