From 447176eb86f88139f9974b789c03444245835874 Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Wed, 10 May 2023 15:20:16 +0200 Subject: Build a markdown version of the readme --- Cargo.toml | 2 +- readme.md | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.org | 7 +- 3 files changed, 337 insertions(+), 4 deletions(-) create mode 100644 readme.md diff --git a/Cargo.toml b/Cargo.toml index 644f4e4..6e66a77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" authors = ["Justin Wernick "] edition = "2021" description = "A shell for restricting access on a version control server" -readme = "readme.org" +readme = "readme.md" # TODO: homepage = "" repository = "https://code.worthe-it.co.za/shackle.git/" license = "MIT" diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..4c4b16b --- /dev/null +++ b/readme.md @@ -0,0 +1,332 @@ + +# Table of Contents + +1. [Getting Started](#org986db7c) + 1. [Usage](#orgafa9ca9) + 2. [Installation](#org549f1c0) + 1. [Prerequisites](#orge3db211) + 2. [Building Shackle](#org201706a) + 3. [Creating the required directory structure](#org7c15c50) + 4. [Set Shackle as your default shell](#orgbbb568c) +2. [Operating System Support](#orgba67b49) +3. [Development Guide](#orgecab73f) + 1. [Development Environment Setup](#org042c092) + 2. [Running Tests](#org47d18c8) + 3. [Linting](#org93c4549) + 4. [Building a Release Binary](#org2f9ca48) +4. [Roadmap / Issue Tracker TODO list](#orgc6e595d) + 1. [MVP](#org63f61f9) + 2. [Post-MVP](#org64e0c30) +5. [License](#org2bca22d) + +A shell for restricting access on a version control server. + +This is intended as a replacement for [Git Shell](https://git-scm.com/docs/git-shell), but with a few opinionated +differences: + +- Additional commands, like creating new repos, are built in. No extension with + shell scripts. +- Strict enforcement of a specified directory structure. Git push / pull + commands only work for these paths. New repos are created in these paths. + - Private git repos are created in `~/git//.git` + - Shared git repos are created in `~/git//.git` +- Better interactive UX than Git Shell, including: + - Command history (limited to the current session). + - Emacs-style shortcuts (eg `Ctrl+a` to move cursor to the beginning of line). + - Docs available for all commands, available in the shell itself. +- (coming soon!) Support for other other version control systems. + + + + +# Getting Started + + + + +## Usage + +Shackle Shell is intended to be set as the default shell for a user on a git +server, where the user connects over SSH (see the Installation section below). + +When you log in over SSH, you'll see a prompt, ready for you to type commands. + + > + +You can see the built in help by running the `help` command. + + > help + Usage: + + Commands: + init Create a new repository + list List all repositories available + set-description Sets the description of a repository, as shown in the CLI listing and web interfaces + set-branch Sets the main branch of the repository + exit Quit the shell + git-upload-pack Server side command required to git fetch from the server + git-receive-pack Server side command required by git push to the server + help Print this message or the help of the given subcommand(s) + + Options: + -h, --help Print help + +The `init` command is used to create a new repo. In its simplest form, you just +provide it with the name of your new repo. This will create a git repo with +individual ownership. + + > init awesome-project-idea + Successfully created "git/shukkie/awesome-project-idea.git" + +The path given here is relative to your home directory. So the full URL to clone +this repo is `@:` + + $ git clone shukkie@example.com:git/shukkie/awesome-project-idea.git + +You can learn its advanced options by using the `--help` flag. This works for +all of the options, and is a great way to learn what all the commands do. + + > init --help + Create a new repository + + Usage: init [OPTIONS] + + Arguments: + Name of the new repository + + Options: + --group Share repository ownership with the specified group (user must be a member of the group) + --description Sets the description of the repository, as shown in the CLI listing and web interfaces + --branch Sets the main branch of the repository [default: main] + -h, --help Print help + + + + +## Installation + + + + +### Prerequisites + +- Git + - This is used for git operations which are passed through for the operation + of `git push` and `git fetch`. + - Git must be installed, with the `git-upload-pack` and `git-receive-pack` + executables on the path. +- SSH + - I assume users will be connecting over SSH. This is not enforced by the + shell, but is the primary use case I have in mind. I have tested this using + the OpenSSH daemon. + + + + +### Building Shackle + +There is not yet a binary release of Shackle, so you need to build it yourself +from source. The easiest way to do this is using `cargo install`. + +This requires a the Rust toolchain and a C compiler. See the Development +Environment Setup section below for more information on environment setup to +build from source. + + # This installs to Cargo's default, which is ~/.cargo/bin. Consider using the + # --root option to install it somewhere that makes more sense for your server. + cargo install --git https://code.worthe-it.co.za/shackle.git/ --force + + + + +### Creating the required directory structure + +Next, Shackle expects a specific directory structure. Specifically, personal git +repos will live in `~/git/your-username` and shared repos will live in +`~/git/your-group`. + +If you have many users on your server, then consider making `~/git` a symlink to +the actual shared location for your git repos. For example, on my repo, all git +users have a `~/git` symlink in their home directory which actually points at +`/srv/git`. + + mkdir -p ~/git/$USER + chmod --recursive u=rwX,g=,o= ~/git/$USER + + # Note that this should be a group you're actually a member of! + GROUP=my-group + mkdir -p ~/git/$GROUP + chown --recursive $USER:$GROUP ~/git/$GROUP + chmod --recursive u=rwX,g=rwXs,o= ~/git/$GROUP + + + + +### Set Shackle as your default shell + +The next step is to set the default shell of your user to Shackle. This will +mean that if you login as the user, for example over ssh, then the default shell +will be Shackle. + + sudo usermod --shell $HOME/.cargo/bin/shackle-shell $USER + + + + +# Operating System Support + +Currently, Shackle Shell only supports running on Linux. + +It will likely work on other Unix-like platforms, such as MacOS, but this is not +currently tested, and there are currently no plans to do so. I would not expect +it to work on Windows. + + + + +# Development Guide + + + + +## Development Environment Setup + +- Rust + - This project is built using the Rust programming language, and its build + tool Cargo. Information on how to install these tools is available on [the + Rust website](https://www.rust-lang.org/learn/get-started). +- C Compiler + - This is used to built one of the dependencies, libgit2. This can be + obtained from your operating system's package manager. +- Docker + - Some of the tests use Docker to create a simulated environment. This can be + obtained from your operating system's package manager, or the [Docker + website](https://www.docker.com/). + - Docker must be installed, with the `docker` executable on the path. + - Your user must have permission to use docker, including building and running + Docker containers. +- Git + - Some of the tests use Git to test the end to end functionality of the + shell. This can be obtained from your operating system's package manager, or + the [Git website](https://git-scm.com/). + - Git must be installed, with the `git` executable on the path. +- SSH + - Some of the tests use an SSH client to test the end to end functionality of + the shell. I have tested this with OpenSSH, which can be obtained from your + operating system's package manager, or the [Git website](https://git-scm.com/). + - with the `ssh` executable on the path. + +If you're running Arch Linux, these are the steps you'll need to get your +environment ready. + + sudo pacman -S rustup docker git openssh gcc + + # Rust + rustup default stable + + # Docker + sudo usermod -a -G docker $USER + sudo systemctl start docker.service + + # Note: you need to log out and in again for the new group to take effect + + + + +## Running Tests + +All unit tests are run with Cargo. + + cargo test --workspace + + + + +## Linting + +Clippy should be used for linting. This can be installed using Rustup. + + rustup component add clippy + +And it can be run via Cargo. + + cargo clippy + + + + +## Building a Release Binary + +Release binaries should be built in release mode. + + cargo build --release + +After running this, the binary is available in `./target/release/shackle-shell` + + + + +# Roadmap / Issue Tracker TODO list + + + + +## MVP + +- [X] interactive command prompt +- [X] non-interactive commands can be run with -c +- [X] exit command +- [X] git init of private repo +- [X] responds to unknown commands +- [X] Isolation of workdir between tests +- [X] git fetch with git upload-pack +- [X] git push with git receive-pack +- [X] proper shell argument lexing, with quote stuff +- [X] history (only within same session) +- [X] don't quit interactive shell sessions if there's an error +- [X] help command +- [X] restrict repos to only acceptable paths + - [X] clone / pull + - [X] push +- [X] git init of shared repos + - [X] create the shared repo in the right place + - [X] use the right file permissions and config + - [X] don't allow this to be a group the user isn't in + - [X] allow pull and push from shared repos +- [X] listing of repos +- [X] set repo descriptions + - [X] init new repo + - [X] change an existing repo +- [X] Change `git-init` name to just be `init`. Later, the `git` part will be an + option which defaults to git. +- [X] set the main branch of a repo +- [X] help docs on all the commands + + + + +## Post-MVP + +- [X] proper licensing +- [X] all the getting started stuff in the readme +- [X] clean up crates.io metadata + - [X] crates.io friendly readme: needs to be markdown + - [X] rename to something that isn't taken on crates.io (shackle-shell) +- [ ] publish to crates.io +- [ ] project website +- [ ] functions correctly when the git path isn't created with correct + permissions yet +- [ ] git archive with git upload-archive +- [ ] git config management around protected branches +- [ ] move a repo to a different group +- [ ] housekeeping git tasks (git fsck, git gc) +- [ ] pijul fetch and pijul push +- [ ] pijul support on other commands + + + + +# License + +Licensed under [MIT License](./LICENSE). + diff --git a/readme.org b/readme.org index e8a140c..d46825a 100644 --- a/readme.org +++ b/readme.org @@ -269,12 +269,13 @@ After running this, the binary is available in =./target/release/shackle-shell= - [X] proper licensing - [X] all the getting started stuff in the readme -- [-] clean up crates.io metadata - - [ ] crates.io friendly readme: needs to be markdown, and probably not all the content of the "full" readme +- [X] clean up crates.io metadata + - [X] crates.io friendly readme: needs to be markdown - [X] rename to something that isn't taken on crates.io (shackle-shell) - [ ] publish to crates.io - [ ] project website -- [ ] functions correctly when the git path isn't created yet +- [ ] functions correctly when the git path isn't created with correct + permissions yet - [ ] git archive with git upload-archive - [ ] git config management around protected branches - [ ] move a repo to a different group -- cgit v1.2.3