Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
Update `radicle-git` to `79a94721366490053e2d8ac1c1afa14fb0c25f09`
xphoniex committed 3 years ago
commit 1f55d7a32750b3e63c56aad00370411b90420a29
parent 9017c591100945497a7196d76d35d0a4f8865690
5 files changed +96 -179
modified Cargo.lock
@@ -86,12 +86,6 @@ checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"

[[package]]
name = "arrayvec"
-
version = "0.5.2"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
-

-
[[package]]
-
name = "arrayvec"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6"
@@ -254,26 +248,14 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"

[[package]]
name = "bitvec"
-
version = "0.19.6"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33"
-
dependencies = [
-
 "funty 1.1.0",
-
 "radium 0.5.3",
-
 "tap",
-
 "wyz 0.2.0",
-
]
-

-
[[package]]
-
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
-
 "funty 2.0.0",
-
 "radium 0.7.0",
+
 "funty",
+
 "radium",
 "tap",
-
 "wyz 0.5.1",
+
 "wyz",
]

[[package]]
@@ -762,12 +744,6 @@ dependencies = [
]

[[package]]
-
name = "either"
-
version = "1.8.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
-

-
[[package]]
name = "elliptic-curve"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -867,7 +843,7 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ade3e9c97727343984e1ceada4fdab11142d2ee3472d2c67027d56b1251d4f15"
dependencies = [
-
 "arrayvec 0.7.2",
+
 "arrayvec",
 "bytes",
 "chrono",
 "elliptic-curve",
@@ -963,12 +939,6 @@ dependencies = [

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

-
[[package]]
-
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
@@ -1058,34 +1028,16 @@ dependencies = [
[[package]]
name = "git-ref-format"
version = "0.1.0"
-
source = "git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481#39ce2f934915a563f9420ac9c85480df8a591481"
-
dependencies = [
-
 "git-ref-format-core 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481)",
-
 "git-ref-format-macro 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481)",
-
]
-

-
[[package]]
-
name = "git-ref-format"
-
version = "0.1.0"
-
source = "git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d#d3115a22158c8395705babefdc89049f7510d32d"
-
dependencies = [
-
 "git-ref-format-core 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d)",
-
 "git-ref-format-macro 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d)",
-
]
-

-
[[package]]
-
name = "git-ref-format-core"
-
version = "0.1.0"
-
source = "git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481#39ce2f934915a563f9420ac9c85480df8a591481"
+
source = "git+https://github.com/radicle-dev/radicle-git?rev=79a94721366490053e2d8ac1c1afa14fb0c25f09#79a94721366490053e2d8ac1c1afa14fb0c25f09"
dependencies = [
-
 "serde",
-
 "thiserror",
+
 "git-ref-format-core",
+
 "git-ref-format-macro",
]

[[package]]
name = "git-ref-format-core"
version = "0.1.0"
-
source = "git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d#d3115a22158c8395705babefdc89049f7510d32d"
+
source = "git+https://github.com/radicle-dev/radicle-git?rev=79a94721366490053e2d8ac1c1afa14fb0c25f09#79a94721366490053e2d8ac1c1afa14fb0c25f09"
dependencies = [
 "serde",
 "thiserror",
@@ -1094,20 +1046,9 @@ dependencies = [
[[package]]
name = "git-ref-format-macro"
version = "0.1.0"
-
source = "git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481#39ce2f934915a563f9420ac9c85480df8a591481"
-
dependencies = [
-
 "git-ref-format-core 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481)",
-
 "proc-macro-error",
-
 "quote",
-
 "syn",
-
]
-

-
[[package]]
-
name = "git-ref-format-macro"
-
version = "0.1.0"
-
source = "git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d#d3115a22158c8395705babefdc89049f7510d32d"
+
source = "git+https://github.com/radicle-dev/radicle-git?rev=79a94721366490053e2d8ac1c1afa14fb0c25f09#79a94721366490053e2d8ac1c1afa14fb0c25f09"
dependencies = [
-
 "git-ref-format-core 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d)",
+
 "git-ref-format-core",
 "proc-macro-error",
 "quote",
 "syn",
@@ -1119,7 +1060,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0934f57135449b88bea0e28efd80aab0c1b53692f8207c7e232086db824c7a8"
dependencies = [
-
 "nom 7.1.1",
+
 "nom",
 "thiserror",
]

@@ -1521,19 +1462,6 @@ dependencies = [
]

[[package]]
-
name = "lexical-core"
-
version = "0.7.6"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
-
dependencies = [
-
 "arrayvec 0.5.2",
-
 "bitflags",
-
 "cfg-if",
-
 "ryu",
-
 "static_assertions",
-
]
-

-
[[package]]
name = "lexopt"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1695,19 +1623,6 @@ dependencies = [

[[package]]
name = "nom"
-
version = "6.1.2"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
-
dependencies = [
-
 "bitvec 0.19.6",
-
 "funty 1.1.0",
-
 "lexical-core",
-
 "memchr",
-
 "version_check",
-
]
-

-
[[package]]
-
name = "nom"
version = "7.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
@@ -1840,7 +1755,7 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce"
dependencies = [
-
 "arrayvec 0.7.2",
+
 "arrayvec",
 "auto_impl",
 "bytes",
 "ethereum-types",
@@ -1902,8 +1817,8 @@ version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "366e44391a8af4cfd6002ef6ba072bae071a96aafca98d7d448a34c5dca38b6a"
dependencies = [
-
 "arrayvec 0.7.2",
-
 "bitvec 1.0.1",
+
 "arrayvec",
+
 "bitvec",
 "byte-slice-cast",
 "impl-trait-for-tuples",
 "parity-scale-codec-derive",
@@ -2151,7 +2066,7 @@ dependencies = [
 "cyphernet",
 "ed25519-compact",
 "fastrand",
-
 "git-ref-format 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481)",
+
 "git-ref-format",
 "git2",
 "log",
 "multibase",
@@ -2210,7 +2125,7 @@ dependencies = [
 "ed25519-compact",
 "fastrand",
 "git-commit",
-
 "git-ref-format 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481)",
+
 "git-ref-format",
 "git-trailers",
 "git2",
 "log",
@@ -2248,7 +2163,7 @@ dependencies = [
 "cyphernet",
 "ed25519-compact",
 "fastrand",
-
 "git-ref-format 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481)",
+
 "git-ref-format",
 "multibase",
 "qcheck",
 "qcheck-macros",
@@ -2265,9 +2180,9 @@ dependencies = [
[[package]]
name = "radicle-git-ext"
version = "0.2.0"
-
source = "git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d#d3115a22158c8395705babefdc89049f7510d32d"
+
source = "git+https://github.com/radicle-dev/radicle-git?rev=79a94721366490053e2d8ac1c1afa14fb0c25f09#79a94721366490053e2d8ac1c1afa14fb0c25f09"
dependencies = [
-
 "git-ref-format 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d)",
+
 "git-ref-format",
 "git2",
 "percent-encoding",
 "radicle-std-ext",
@@ -2315,7 +2230,7 @@ dependencies = [
 "crossbeam-channel",
 "cyphernet",
 "fastrand",
-
 "git-ref-format 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481)",
+
 "git-ref-format",
 "lexopt",
 "log",
 "nakamoto-net",
@@ -2357,23 +2272,22 @@ dependencies = [
[[package]]
name = "radicle-std-ext"
version = "0.1.0"
-
source = "git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d#d3115a22158c8395705babefdc89049f7510d32d"
+
source = "git+https://github.com/radicle-dev/radicle-git?rev=79a94721366490053e2d8ac1c1afa14fb0c25f09#79a94721366490053e2d8ac1c1afa14fb0c25f09"

[[package]]
name = "radicle-surf"
version = "0.8.0"
-
source = "git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d#d3115a22158c8395705babefdc89049f7510d32d"
+
source = "git+https://github.com/radicle-dev/radicle-git?rev=79a94721366490053e2d8ac1c1afa14fb0c25f09#79a94721366490053e2d8ac1c1afa14fb0c25f09"
dependencies = [
 "anyhow",
 "base64",
-
 "either",
 "flate2",
-
 "git-ref-format 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=d3115a22158c8395705babefdc89049f7510d32d)",
+
 "git-ref-format",
 "git2",
-
 "nom 6.1.2",
+
 "log",
 "nonempty 0.5.0",
 "radicle-git-ext",
-
 "regex",
+
 "radicle-std-ext",
 "serde",
 "tar",
 "thiserror",
@@ -2384,18 +2298,12 @@ name = "radicle-tools"
version = "0.2.0"
dependencies = [
 "anyhow",
-
 "git-ref-format 0.1.0 (git+https://github.com/radicle-dev/radicle-git?rev=39ce2f934915a563f9420ac9c85480df8a591481)",
+
 "git-ref-format",
 "radicle",
]

[[package]]
name = "radium"
-
version = "0.5.3"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
-

-
[[package]]
-
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
@@ -3642,12 +3550,6 @@ checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"

[[package]]
name = "wyz"
-
version = "0.2.0"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
-

-
[[package]]
-
name = "wyz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
modified Cargo.toml
@@ -46,8 +46,8 @@ version = "0.1.0"

[patch.crates-io.radicle-git-ext]
git = "https://github.com/radicle-dev/radicle-git"
-
rev = "d3115a22158c8395705babefdc89049f7510d32d"
+
rev = "79a94721366490053e2d8ac1c1afa14fb0c25f09"

[patch.crates-io.git-ref-format]
git = "https://github.com/radicle-dev/radicle-git"
-
rev = "39ce2f934915a563f9420ac9c85480df8a591481"
+
rev = "79a94721366490053e2d8ac1c1afa14fb0c25f09"
modified radicle-httpd/Cargo.toml
@@ -41,5 +41,5 @@ version = "0.2.0"

[dependencies.radicle-surf]
git = "https://github.com/radicle-dev/radicle-git"
-
features = ["serialize"]
-
rev = "d3115a22158c8395705babefdc89049f7510d32d"
+
features = ["serde"]
+
rev = "79a94721366490053e2d8ac1c1afa14fb0c25f09"
modified radicle-httpd/src/api/error.rs
@@ -18,22 +18,6 @@ pub enum Error {
    #[error(transparent)]
    Env(#[from] std::env::VarError),

-
    /// I/O error.
-
    #[error("i/o error: {0}")]
-
    Io(#[from] std::io::Error),
-

-
    /// Invalid identifier.
-
    #[error("invalid radicle identifier: {0}")]
-
    Id(#[from] radicle::identity::IdError),
-

-
    /// HeaderName error.
-
    #[error(transparent)]
-
    InvalidHeaderName(#[from] axum::http::header::InvalidHeaderName),
-

-
    /// HeaderValue error.
-
    #[error(transparent)]
-
    InvalidHeaderValue(#[from] axum::http::header::InvalidHeaderValue),
-

    /// An error occurred while verifying the siwe message.
    #[error(transparent)]
    SiweVerification(#[from] siwe::VerificationError),
@@ -56,11 +40,11 @@ pub enum Error {

    /// Surf commit error.
    #[error(transparent)]
-
    SurfCommit(#[from] radicle_surf::commit::Error),
+
    SurfCommit(#[from] radicle_surf::source::commit::Error),

    /// Surf object error.
    #[error(transparent)]
-
    SurfObject(#[from] radicle_surf::object::Error),
+
    SurfObject(#[from] radicle_surf::source::object::Error),

    /// Surf git error.
    #[error(transparent)]
modified radicle-httpd/src/api/v1/projects.rs
@@ -1,4 +1,4 @@
-
use std::collections::HashSet;
+
use std::collections::{BTreeMap, HashSet};

use axum::handler::Handler;
use axum::http::{header, HeaderValue};
@@ -13,12 +13,15 @@ use tower_http::set_header::SetResponseHeaderLayer;
use radicle::cob::issue::Issues;
use radicle::cob::thread::{self, CommentId};
use radicle::cob::Timestamp;
-
use radicle::git::raw::BranchType;
+
use radicle::git::Oid;
use radicle::identity::{Id, PublicKey};
use radicle::node::NodeId;
-
use radicle::storage::{Oid, ReadRepository, WriteRepository, WriteStorage};
-
use radicle_surf::git::History;
-
use radicle_surf::Revision::Sha;
+
use radicle::storage::git::paths;
+
use radicle::storage::{ReadRepository, WriteStorage};
+
use radicle_surf::git::{Glob, History, Repository};
+
use radicle_surf::source;
+
use radicle_surf::source::object::blob::Blob;
+
use radicle_surf::source::object::tree::Tree;

use crate::api::axum_extra::{Path, Query};
use crate::api::error::Error;
@@ -133,7 +136,7 @@ async fn history_handler(
    };

    let storage = &ctx.profile.storage;
-
    let repo = storage.repository(project)?;
+
    let repo = Repository::open(paths::repository(storage, &project))?;

    // If a pagination is defined, we do not want to paginate the commits, and we return all of them on the first page.
    let page = page.unwrap_or(0);
@@ -143,7 +146,8 @@ async fn history_handler(
        per_page.unwrap_or(30)
    };

-
    let headers = History::new(repo.raw().into(), sha.as_str())?
+
    let headers = repo
+
        .history(sha)?
        .filter(|q| {
            if let Ok(q) = q {
                if let (Some(since), Some(until)) = (since, until) {
@@ -164,7 +168,7 @@ async fn history_handler(
        .take(per_page)
        .filter_map(|commit| {
            if let Ok(commit) = commit {
-
                radicle_surf::commit(&repo.raw().into(), commit.id).ok()
+
                source::commit(&repo, commit.id).ok()
            } else {
                None
            }
@@ -173,7 +177,7 @@ async fn history_handler(

    let response = json!({
        "headers": headers,
-
        "stats":  stats(&repo)?,
+
        "stats":  repo.stats()?,
    });

    if fallback_to_head {
@@ -190,8 +194,8 @@ async fn commit_handler(
    Path((project, sha)): Path<(Id, Oid)>,
) -> impl IntoResponse {
    let storage = &ctx.profile.storage;
-
    let repo = storage.repository(project)?;
-
    let commit = radicle_surf::commit(&repo.raw().into(), sha)?;
+
    let repo = Repository::open(paths::repository(storage, &project))?;
+
    let commit = source::commit(&repo, sha)?;

    Ok::<_, Error>(Json(commit))
}
@@ -205,9 +209,10 @@ async fn activity_handler(
    let current_date = chrono::Utc::now().timestamp();
    let one_year_ago = chrono::Duration::weeks(52);
    let storage = &ctx.profile.storage;
-
    let repo = storage.repository(project)?;
-
    let (_, head) = repo.head()?;
-
    let timestamps = History::new(repo.raw().into(), head)?
+
    let repo = Repository::open(paths::repository(storage, &project))?;
+
    let head = repo.head()?;
+
    let timestamps = repo
+
        .history(head)?
        .filter_map(|a| {
            if let Ok(a) = a {
                let seconds = a.committer.time.seconds();
@@ -230,14 +235,11 @@ async fn tree_handler(
) -> impl IntoResponse {
    let path = path.strip_prefix('/').ok_or(Error::NotFound)?.to_string();
    let storage = &ctx.profile.storage;
-
    let repo = storage.repository(project)?;
-
    let tree = radicle_surf::object::tree(&repo.raw().into(), Some(Sha { sha }), Some(path))?;
-
    let response = json!({
-
        "path": &tree.path,
-
        "entries": &tree.entries,
-
        "info": &tree.info,
-
        "stats": stats(&repo)?,
-
    });
+
    let repo = Repository::open(paths::repository(storage, &project))?;
+
    let path = if path.is_empty() { None } else { Some(&path) };
+
    let tree = Tree::new(&repo, &sha, path)?;
+
    let mut response = json!(tree);
+
    response["stats"] = json!(stats(&repo, sha)?);

    Ok::<_, Error>(Json(response))
}
@@ -253,6 +255,23 @@ async fn remotes_handler(
    let remotes = repo
        .remotes()?
        .filter_map(|r| r.map(|r| r.1).ok())
+
        .map(|remote| {
+
            let refs = remote
+
                .refs
+
                .iter()
+
                .filter_map(|(r, oid)| {
+
                    r.as_str()
+
                        .strip_prefix("refs/heads/")
+
                        .map(|head| (head.to_string(), oid))
+
                })
+
                .collect::<BTreeMap<String, &Oid>>();
+

+
            json!({
+
                "id": remote.id,
+
                "heads": refs,
+
                "delegate": remote.delegate,
+
            })
+
        })
        .collect::<Vec<_>>();

    Ok::<_, Error>(Json(remotes))
@@ -267,6 +286,20 @@ async fn remote_handler(
    let storage = &ctx.profile.storage;
    let repo = storage.repository(project)?;
    let remote = repo.remote(&node_id)?;
+
    let refs = remote
+
        .refs
+
        .iter()
+
        .filter_map(|(r, oid)| {
+
            r.as_str()
+
                .strip_prefix("refs/heads/")
+
                .map(|head| (head.to_string(), oid))
+
        })
+
        .collect::<BTreeMap<String, &Oid>>();
+
    let remote = json!({
+
        "id": remote.id,
+
        "heads": refs,
+
        "delegate": remote.delegate,
+
    });

    Ok::<_, Error>(Json(remote))
}
@@ -279,8 +312,8 @@ async fn blob_handler(
) -> impl IntoResponse {
    let path = path.strip_prefix('/').ok_or(Error::NotFound)?;
    let storage = &ctx.profile.storage;
-
    let repo = storage.repository(project)?;
-
    let blob = radicle_surf::blob::blob(&repo.raw().into(), Some(Sha { sha }), path)?;
+
    let repo = Repository::open(paths::repository(storage, &project))?;
+
    let blob = Blob::new(&repo, &sha, &path)?;

    Ok::<_, Error>(Json(blob))
}
@@ -292,7 +325,7 @@ async fn readme_handler(
    Path((project, sha)): Path<(Id, Oid)>,
) -> impl IntoResponse {
    let storage = &ctx.profile.storage;
-
    let repo = storage.repository(project)?;
+
    let repo = Repository::open(paths::repository(storage, &project))?;
    let paths = &[
        "README",
        "README.md",
@@ -303,14 +336,12 @@ async fn readme_handler(
    ];

    for path in paths {
-
        if let Ok(blob) = radicle_surf::blob::blob(&repo.raw().into(), Some(Sha { sha }), path) {
+
        if let Ok(blob) = Blob::new(&repo, &sha, &path) {
            return Ok::<_, Error>(Json(blob));
        }
    }

-
    Err(radicle_surf::object::Error::PathNotFound(
-
        radicle_surf::file_system::Path::try_from("README").unwrap(),
-
    ))?
+
    Err(Error::NotFound)
}

/// Get project issues list.
@@ -413,11 +444,11 @@ struct Stats {
    contributors: usize,
}

-
fn stats<R: WriteRepository>(repo: &R) -> Result<Stats, Error> {
-
    let branches = repo.raw().branches(Some(BranchType::Local))?.count();
-
    let (_, head) = repo.head()?;
+
fn stats(repo: &Repository, head: Oid) -> Result<Stats, Error> {
+
    let branches = repo.branches(Glob::all_heads())?.count();
+

    let mut commits = 0;
-
    let contributors = History::new(repo.raw().into(), head)?
+
    let contributors = History::new(repo, head)?
        .filter_map(|commit| {
            commits += 1;
            if let Ok(commit) = commit {