# Table of Contents 1. [Getting Started](#org9c3903e) 1. [Usage](#org6fa9d8a) 2. [Installation](#org10b2c96) 1. [Prerequisites](#orgd426ed1) 2. [Building Shackle](#orgb7eee70) 3. [Creating the required directory structure](#orgf8fd81a) 4. [Set Shackle as your default shell](#org58e1057) 2. [Operating System Support](#org8418be0) 3. [Development Guide](#org8b93b3d) 1. [Development Environment Setup](#org6250a5d) 2. [Running Tests](#org7f14941) 3. [Linting](#orgc006671) 4. [Building a Release Binary](#orgcd5123a) 4. [Roadmap / Issue Tracker TODO list](#orgba8330a) 1. [MVP](#org565bb14) 2. [Post-MVP](#org50cfb78) 5. [License](#org013cf1e) 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 shackle-shell ### 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 ## 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).