⛏️ index : gitore.git

author Alexander von Gluck <alex@terarocket.io> 2025-11-21 16:13:11.0 -06:00:00
committer Alexander von Gluck <alex@terarocket.io> 2025-11-21 16:13:14.0 -06:00:00
commit
99ea2d10e1b634edb5ad2959aeeda01071bce210 [patch]
tree
beaf060e6e17a05de4709fb57bcbd71ed2375205
parent
3dfcb7f0ec622b6f20b9827510869710d4d106df
download
99ea2d10e1b634edb5ad2959aeeda01071bce210.tar.gz

rebrand/cleanup: Forking under a new name. gitore

The authors of rgit did some great work, however there
are a lot of cleanups and improvements that could be made.

After a brief interaction with the small community, i'm under the
opinion that it wasn't very healthy.

I'm forking, and working on this to improve a lot of areas which
were limited:

  * Improve memory management on big repositories
  * Improve user/admin experiences
  * Improve cgit compatibility
  * Cleanup packaging, don't use nix as a crutch

Diff

 Cargo.lock                          | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
 Cargo.toml                          |   6 ++----
 README.md                           | 107 ++++++++++----------------------------------------------------------------------
 build.rs                            |   2 +-
 cliff.toml                          |  61 -------------------------------------------------------------
 docker-compose.override.yml.example |  16 ----------------
 docker-compose.yml                  |   2 +-
 gitore.png                          |   0 
 src/main.rs                         |   2 +-
 templates/base.html                 |   4 ++--
 doc/man/rgit.1.md                   | 105 --------------------------------------------------------------------------------
 scripts/docker/entrypoint.sh        |   2 --
 src/methods/repo/diff.rs            |   2 +-
 src/methods/repo/snapshot.rs        |   2 +-
 14 files changed, 86 insertions(+), 375 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 4075fae..d96d531 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -86,7 +86,7 @@
 "memchr",
 "proc-macro2",
 "quote",
 "rustc-hash 2.1.1",
 "rustc-hash",
 "syn",
]

@@ -216,20 +216,18 @@

[[package]]
name = "bindgen"
version = "0.69.5"
version = "0.72.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895"
dependencies = [
 "bitflags",
 "cexpr",
 "clang-sys",
 "itertools",
 "lazy_static",
 "lazycell",
 "proc-macro2",
 "quote",
 "regex",
 "rustc-hash 1.1.0",
 "rustc-hash",
 "shlex",
 "syn",
]
@@ -770,6 +768,58 @@
version = "0.31.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"

[[package]]
name = "gitore"
version = "0.1.5"
dependencies = [
 "anyhow",
 "arc-swap",
 "askama",
 "axum",
 "axum-extra",
 "basic-toml",
 "bytes",
 "clap",
 "comrak",
 "const-hex",
 "const_format",
 "flate2",
 "futures-util",
 "gix",
 "hashbrown",
 "httparse",
 "humantime",
 "itertools",
 "md5",
 "memchr",
 "moka",
 "path-clean",
 "rand",
 "rkyv",
 "rocksdb",
 "rsass",
 "serde",
 "simdutf8",
 "tar",
 "time",
 "timeago",
 "tokio",
 "tokio-stream",
 "tokio-util",
 "tower-http",
 "tower-layer",
 "tower-service",
 "tracing",
 "tracing-subscriber",
 "tree-sitter-grammar-repository",
 "tree-sitter-highlight",
 "unix_mode",
 "uuid",
 "v_htmlescape",
 "xxhash-rust",
 "yoke",
]

[[package]]
name = "gix"
@@ -1485,9 +1535,9 @@

[[package]]
name = "globset"
version = "0.4.16"
version = "0.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
checksum = "52dfc19153a48bde0cbd630453615c8151bce3a5adfac7a0aebfbf0a1e1f57e3"
dependencies = [
 "aho-corasick",
 "bstr",
@@ -1515,9 +1565,9 @@

[[package]]
name = "hermit-abi"
version = "0.3.9"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"

[[package]]
name = "hex"
@@ -1849,12 +1899,6 @@
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"

[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"

[[package]]
name = "libc"
@@ -1875,9 +1919,9 @@

[[package]]
name = "librocksdb-sys"
version = "0.17.1+9.9.3"
version = "0.17.3+10.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b7869a512ae9982f4d46ba482c2a304f1efd80c6412a3d4bf57bb79a619679f"
checksum = "cef2a00ee60fe526157c9023edab23943fae1ce2ab6f4abb2a807c1746835de9"
dependencies = [
 "bindgen",
 "bzip2-sys",
@@ -2136,9 +2180,9 @@

[[package]]
name = "num_cpus"
version = "1.16.0"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
dependencies = [
 "hermit-abi",
 "libc",
@@ -2256,9 +2300,9 @@

[[package]]
name = "prettyplease"
version = "0.2.32"
version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6"
checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55"
dependencies = [
 "proc-macro2",
 "syn",
@@ -2436,58 +2480,6 @@
checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215"
dependencies = [
 "bytecheck",
]

[[package]]
name = "rgit"
version = "0.1.5"
dependencies = [
 "anyhow",
 "arc-swap",
 "askama",
 "axum",
 "axum-extra",
 "basic-toml",
 "bytes",
 "clap",
 "comrak",
 "const-hex",
 "const_format",
 "flate2",
 "futures-util",
 "gix",
 "hashbrown",
 "httparse",
 "humantime",
 "itertools",
 "md5",
 "memchr",
 "moka",
 "path-clean",
 "rand",
 "rkyv",
 "rocksdb",
 "rsass",
 "serde",
 "simdutf8",
 "tar",
 "time",
 "timeago",
 "tokio",
 "tokio-stream",
 "tokio-util",
 "tower-http",
 "tower-layer",
 "tower-service",
 "tracing",
 "tracing-subscriber",
 "tree-sitter-grammar-repository",
 "tree-sitter-highlight",
 "unix_mode",
 "uuid",
 "v_htmlescape",
 "xxhash-rust",
 "yoke",
]

[[package]]
@@ -2519,9 +2511,9 @@

[[package]]
name = "rocksdb"
version = "0.23.0"
version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26ec73b20525cb235bad420f911473b69f9fe27cc856c5461bccd7e4af037f43"
checksum = "ddb7af00d2b17dbd07d82c0063e25411959748ff03e8d4f96134c2ff41fce34f"
dependencies = [
 "libc",
 "librocksdb-sys",
@@ -2549,12 +2541,6 @@
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"

[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"

[[package]]
name = "rustc-hash"
diff --git a/Cargo.toml b/Cargo.toml
index 4977fcf..7dd831f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,15 +1,13 @@
[package]
name = "rgit"
name = "gitore"
description = "A gitweb/cgit-like interface"
version = "0.1.5"
edition = "2024"
authors = ["Jordan Doyle <jordan@doyle.la>"]
authors = ["Jordan Doyle <jordan@doyle.la>", "Alexander von Gluck <alex@terarocket.io>"]
license = "WTFPL"

[workspace]
members = ["tree-sitter-grammar-repository"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0"
diff --git a/README.md b/README.md
index f3e64d0..b918653 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
# rgit
# gitore

## Introduction
![gitore](gitore.png)

[See it in action!](https://git.inept.dev/)
## Introduction

A gitweb/cgit-like interface for the modern age. Written in Rust using Axum, gitoxide, Askama and RocksDB.

@@ -19,9 +19,6 @@
  - [Configuration](#configuration)
    - [Repository Description](#repository-description)

    - [Repository Owner](#repository-owner)

  - [NixOS](#nixos)
  - [Docker](#docker)
    - [Docker Compose](#docker-compose)

- [Contributing](#contributing)
- [License](#license)
- [Troubleshooting](#troubleshooting)
@@ -57,33 +54,13 @@
**Note:** This software is designed to work exclusively with bare Git repositories. Make sure to set up bare repositories beforehand by following the [Git on the Server documentation][].

[Git on the Server documentation]: https://git-scm.com/book/en/v2/Git-on-the-Server-Getting-Git-on-a-Server

### Installation

#### Cargo (automatic)

```shell

cargo install --git https://github.com/w4/rgit
```


#### From Source (manually)

Clone the repository and build:

```shell

git clone https://github.com/w4/rgit.git
cd rgit
cargo build --release
```


The rgit binary will be found in the `target/release` directory.

### Usage

To get up and running quickly, run rgit with the following:
To get up and running quickly, run gitore with the following:

```shell

rgit [::]:3333 /path/to/my-bare-repos -d /tmp/rgit-cache.db
gitore [::]:3333 /path/to/my-bare-repos -d /tmp/gitore-cache.db
```


**Notes:**
@@ -107,83 +84,17 @@

Replace `Al Gorithm` with the desired owner's name.

### NixOS

Running rgit on NixOS is straightforward, simply import the module into your `flake.nix`
and use the provided service:

```nix

{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.05";


    rgit = {

      url = "github:w4/rgit";

      inputs.nixpkgs = "nixpkgs";

    };

  };

  outputs = { nixpkgs, ... }: {
    nixosConfigurations.mySystem = nixpkgs.lib.nixosSystem {

      modules = [

        rgit.nixosModules.default

        {

          services.rgit = {

            enable = true;

            bindAddress = "[::]:3333";

            dbStorePath = "/tmp/rgit.db";

            repositoryStorePath = "/path/to/my-bare-repos";

          };

        }

        ...

      ];

    };

  };
}
```


### Docker

Running rgit in Docker is straightforward. Follow these steps, ensuring that your repository directory is correctly mounted:
Running gitore in Docker is straightforward. Follow these steps, ensuring that your repository directory is correctly mounted:

```shell

docker run --mount type=bind,source=/path/to/my-bare-repos,target=/git \
  --user $UID:$GID \
  -it ghcr.io/w4/rgit:main
  -it codeberg.org/kallisti5/gitore:latest
```


**Note**: Replace `$UID` and `$GID` with the UID and GID of the user that owns the directory containing your repositories. If these values are incorrect, errors will occur. Learn how to find the UID of a user [here](https://linuxhandbook.com/uid-linux/).

#### Docker Compose

An example `docker-compose.yml` is provided for those who prefer using Compose. To configure
the UID and GID, the user can be specified in `docker-compose.override.yml`.

An example override file has been has been provided with the repository. To use it, remove the
`.example` extension from `docker-compose.override.yml.example`, and adjust the UID and GID to
match the user that owns the directory containing your repositories.

To configure automatic refresh in Docker, an environment variable is also provided.

```yml

version: '3'
services:
  rgit:
    image: ghcr.io/w4/rgit:main

    command:

      - "[::]:8000"

      - /git

      - -d /tmp/rgit-cache.db

    volumes:

      - /volume/git:/git

    ports:

      - 8000:8000

    environment:

      - REFRESH_INTERVAL=5m

    restart: unless-stopped

```


Afterwards, bring up the container with `docker-compose up` to make sure everything works.

## Contributing

@@ -191,7 +102,7 @@

## License

rgit is licensed under the [WTFPL](LICENSE).
gitore is licensed under the [WTFPL](LICENSE).

## Troubleshooting

@@ -223,7 +134,7 @@
```


**Solution:**
Ensure that the user launching `rgit` or the Docker container has the same permissions as the user that owns the repositories directory.
Ensure that the user launching `gitore` or the Docker container has the same permissions as the user that owns the repositories directory.

### Application Usage

diff --git a/build.rs b/build.rs
index b16d138..db90b58 100644
--- a/build.rs
+++ b/build.rs
@@ -13,7 +13,7 @@

fn main() {
    if let Err(e) = run() {
        eprintln!("An error occurred within the rgit build script:\n\n{:?}", e);
        eprintln!("An error occurred within the gitore build script:\n\n{:?}", e);
        std::process::exit(1);
    }
}
diff --git a/cliff.toml b/cliff.toml
deleted file mode 100644
index bda6cec..0000000 100644
--- a/cliff.toml
+++ /dev/null
@@ -1,61 +1,0 @@
[remote.github]
owner = "w4"
repo = "rgit"

[changelog]
body = """
## What's Changed

{%- if version %} in {{ version }}{%- endif -%}
{% for commit in commits %}
  {% if commit.remote.pr_title -%}
    {%- set commit_message = commit.remote.pr_title -%}
  {%- else -%}
    {%- set commit_message = commit.message -%}
  {%- endif -%}
  * [{{ commit_message | split(pat="\n") | first | trim }}]({{ self::remote_url() }}/commit/{{ commit.id }})\
    {% if commit.remote.username %} by @{{ commit.remote.username }}{% else %} by {{ commit.author.name }}{%- endif -%}
    {% if commit.remote.pr_number %} in \
      [#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.remote.pr_number }}) \
    {%- endif %}
{%- endfor -%}

{%- if github -%}
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
  {% raw %}\n{% endraw -%}
  ## New Contributors
{%- endif %}\
{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}
  * @{{ contributor.username }} made their first contribution
    {%- if contributor.pr_number %} in \
      [#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
    {%- endif %}
{%- endfor -%}
{%- endif -%}

{% if version %}
    {% if previous.version %}
      **Full Changelog**: {{ self::remote_url() }}/compare/{{ previous.version }}...{{ version }}
    {% endif %}
{% else -%}
  {% raw %}\n{% endraw %}
{% endif %}

{%- macro remote_url() -%}
  https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
{%- endmacro -%}
"""
trim = true
footer = """
<!-- generated by git-cliff -->
"""
postprocessors = []

[git]
conventional_commits = false
filter_unconventional = false
split_commits = false
commit_preprocessors = [{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" }]
filter_commits = false
topo_order = false
sort_commits = "newest"
diff --git a/docker-compose.override.yml.example b/docker-compose.override.yml.example
deleted file mode 100644
index 2fc6726..0000000 100644
--- a/docker-compose.override.yml.example
+++ /dev/null
@@ -1,16 +1,0 @@
version: '3'
services:
  rgit:
    image: ghcr.io/w4/rgit:main
    user: 1000:1000
    command:
      - "[::]:8000"
      - /git
      - -d /tmp/rgit-cache.db
    volumes:
      - /volume/git:/git
    ports:
      - 8000:8000
    environment:
      - REFRESH_INTERVAL=5m
    restart: unless-stopped
diff --git a/docker-compose.yml b/docker-compose.yml
index 81b086a..25901d1 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,7 +1,7 @@
version: '3'
services:
  rgit:
    image: ghcr.io/w4/rgit:main
    image: codeberg.org/kallisti5/gitore:latest
    volumes:
      - /volume/git:/git
    ports:
diff --git a/gitore.png b/gitore.png
new file mode 100644
index 0000000000000000000000000000000000000000..240672e1ddcf7522f6aaa0f5f4a3480f2e91dab6 100644
Binary files /dev/null and b/gitore.png differdiff --git a/src/main.rs b/src/main.rs
index aeb2266..c913dac 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -83,7 +83,7 @@
    #[clap(short, long, env="DB_STORE", value_parser)]
    db_store: PathBuf,
    /// Optional path (relative to cwd) to a plain text file containing a list of repositories relative to the `scan_path`

    /// that are whitelisted to be exposed by rgit.

    /// that are whitelisted to be exposed by gitore.

    #[clap(long, env="REPOSITORY_LIST")]
    repository_list: Option<PathBuf>,
    /// Configures the metadata refresh interval (eg. "never" or "60s")

diff --git a/templates/base.html b/templates/base.html
index cc8e66f..92d91dd 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -1,9 +1,9 @@
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>{% block title %}rgit{% endblock %}</title>
    <title>{% block title %}gitore{% endblock %}</title>
    <link rel="stylesheet" type="text/css" href="/style-{{ crate::GLOBAL_CSS_HASH }}.css" />
    {%- block head -%}{%- endblock %}
</head>
@@ -39,7 +39,7 @@
</main>

<footer>
    generated by <a href="https://git.inept.dev/~doyle/rgit.git/about" target="_blank">rgit</a> v{{ crate::CRATE_VERSION }}
    generated by <a href="https://codeberg.org/kallisti5/gitore" target="_blank">gitore</a> v{{ crate::CRATE_VERSION }}
    at {{ time::OffsetDateTime::now_utc()|format_time }}
    in {{ "{:?}"|format(crate::layers::logger::REQ_TIMESTAMP.get().elapsed()) }}
</footer>
diff --git a/doc/man/rgit.1.md b/doc/man/rgit.1.md
deleted file mode 100644
index f0270b3..0000000 100644
--- a/doc/man/rgit.1.md
+++ /dev/null
@@ -1,105 +1,0 @@
% RGIT(1) version 0.1.2 | User Commands
%
% 11 January 2024

NAME
====

rgit - a gitweb interface written in rust

SYNOPSIS
========

| **rgit** \[*OPTIONS*] **\--db-store** *path* *bind_address* *scan_path*

DESCRIPTION
===========

A gitweb/cgit-like interface for the modern age. Written in Rust using Axum, gitoxide, Askama, and RocksDB.  
  
_bind_address_ 

:   Specifies the network address and port to serve the application on.
(Required)  

    Example:


    :   _0.0.0.0:3333_ (localhost, port 3333 on IPv4)


        _[::]:3333_ (localhost, port 3333 on IPv6)  


_scan_path_ 

:   Specifies the root directory where git repositories reside. Scans recursively.
(Required)  
  
    For information about bare git repositories, see the manual for **git-init**(1).  


    Example:


    :   _/srv/git_


        _$HOME/git_



OPTIONS
=======

**-d** _path_, **\--db-store** _path_

:   Path to a directory in which the RocksDB database should be stored, will be created if it doesn't already exist.  

    The RocksDB database is very quick to generate, so this can be pointed to temporary storage. (Required)


    Example:


    :   **\--db-store** _/tmp/rgit-cache.db_


**\--refresh-interval** _interval_

:   Configures the metadata refresh interval. This parameter accepts human-readable time formats.

    Default: _5m_


    Example:


    :   **\--refresh-interval** _60s_ (refresh every 60 seconds)


        **\--refresh-interval** _never_ (refresh only on server start)


    Documentation:


    :    https://docs.rs/humantime/latest/humantime/


EXAMPLES
========

```

$ rgit -d /tmp/rgit-cache.db [::]:3333 /srv/git
$ rgit --db-store /tmp/rgit-cache.db 0.0.0.0:3333 /srv/git
$ rgit -d /tmp/rgit-cache.db [::]:3333 /srv/git --refresh-interval 12h

```


BUGS
====

https://github.com/w4/rgit/issues

AUTHORS
=======

Jordan Doyle \<jordan@doyle.la>

REPOSITORY
==========

https://git.inept.dev/~doyle/rgit.git

https://github.com/w4/rgit

SEE ALSO
========

**git**(1),
**git-init**(1)
diff --git a/scripts/docker/entrypoint.sh b/scripts/docker/entrypoint.sh
deleted file mode 100755
index ea506c8..0000000 100755
--- a/scripts/docker/entrypoint.sh
+++ /dev/null
@@ -1,2 +1,0 @@
#!/usr/bin/env bash
./rgit "[::]:8000" /git -d /tmp/rgit-cache.db;
diff --git a/src/methods/repo/diff.rs b/src/methods/repo/diff.rs
index 767e731..7f4cd44 100644
--- a/src/methods/repo/diff.rs
+++ b/src/methods/repo/diff.rs
@@ -98,7 +98,7 @@
    data.extend_from_slice(b"\n");
    data.extend_from_slice(commit.diff.as_bytes());

    writeln!(data, "--\nrgit {}", crate_version!()).unwrap();
    writeln!(data, "--\ngitore {}", crate_version!()).unwrap();

    Ok((headers, data.freeze()).into_response())
}
diff --git a/src/methods/repo/snapshot.rs b/src/methods/repo/snapshot.rs
index c97ff4b..94ecff1 100644
--- a/src/methods/repo/snapshot.rs
+++ b/src/methods/repo/snapshot.rs
@@ -61,7 +61,7 @@
        // ok, well this isn't ideal. the sender disappeared but we never got
        // an error. this shouldn't be possible, i guess lets just return an
        // internal error
        return Err(anyhow!("Ran into inconsistent error state whilst building archive, please file an issue at https://github.com/w4/rgit/issues").into());
        return Err(anyhow!("Ran into inconsistent error state whilst building archive, please file an issue at https://codeberg.org/kallisti5/gitore").into());
    }

    let file_name = query