Compare commits

..

25 Commits

Author SHA1 Message Date
42c094a7d7 chore: Bump version (v0.23.0)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2022-08-23 12:19:00 +02:00
330c21b12c Merge pull request #484 from vbrandl/fix/docker-build
All checks were successful
continuous-integration/drone/push Build is passing
Use different rust-musl image
2022-08-23 11:39:27 +02:00
9a0d8dfc37 Use different rust-musl image
All checks were successful
continuous-integration/drone/push Build is passing
2022-08-23 11:36:08 +02:00
633873814b Merge pull request #480 from vbrandl/feature/ructe-static
Use ructe static file support to serve static files with hashes and caching
2022-08-23 10:09:02 +02:00
95c54b95c1 Remove unnecessary testcase 2022-08-23 09:45:05 +02:00
a68a49f6ae Merge branch 'master' into feature/ructe-static 2022-08-22 15:34:49 +02:00
6c7cb9df97 Merge pull request #478 from Masynchin/count
Some checks failed
continuous-integration/drone/push Build is failing
Refactor count_repositories
2022-08-22 15:34:32 +02:00
0a4ec4ecd4 Run fmt 2022-08-22 16:20:24 +03:00
3ead212fe7 Add tests for count_repositories 2022-08-22 16:12:21 +03:00
b001db6558 Merge branch 'master' into feature/ructe-static 2022-08-22 12:28:56 +02:00
5543301140 Merge pull request #477 from vbrandl/feature/branch-in-generator
Allow providing a branch name in generator
2022-08-22 11:57:05 +02:00
028795effa Merge branch 'master' into feature/branch-in-generator 2022-08-22 11:53:39 +02:00
23303d818a Merge branch 'master' into feature/ructe-static 2022-08-22 11:50:45 +02:00
886caeca1c Merge pull request #476 from vbrandl/dependabot/cargo/futures-0.3.23
chore(deps): Bump futures from 0.3.21 to 0.3.23
2022-08-22 11:47:03 +02:00
6fbd437f34 Merge pull request #482 from vbrandl/dependabot/cargo/serde_json-1.0.85
chore(deps): Bump serde_json from 1.0.83 to 1.0.85
2022-08-22 11:46:55 +02:00
13095b0445 Merge pull request #483 from vbrandl/dependabot/cargo/serde-1.0.144
chore(deps): Bump serde from 1.0.143 to 1.0.144
2022-08-22 11:46:46 +02:00
6c8a635e12 chore(deps): Bump futures from 0.3.21 to 0.3.23
Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.21 to 0.3.23.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.21...0.3.23)

---
updated-dependencies:
- dependency-name: futures
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-22 09:36:58 +00:00
d0ea0c8a68 chore(deps): Bump serde_json from 1.0.83 to 1.0.85
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.83 to 1.0.85.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.83...v1.0.85)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-22 09:36:57 +00:00
6bd843d9b8 chore(deps): Bump serde from 1.0.143 to 1.0.144
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.143 to 1.0.144.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.143...v1.0.144)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-22 09:36:47 +00:00
f4206140b3 Merge pull request #481 from vbrandl/dependabot/cargo/ructe-0.14.2
chore(deps): Bump ructe from 0.14.0 to 0.14.2
2022-08-22 11:35:51 +02:00
7139663544 Add docs to count_repositories 2022-08-22 10:51:57 +03:00
0c9ef2abd2 chore(deps): Bump ructe from 0.14.0 to 0.14.2
Bumps [ructe](https://github.com/kaj/ructe) from 0.14.0 to 0.14.2.
- [Release notes](https://github.com/kaj/ructe/releases)
- [Changelog](https://github.com/kaj/ructe/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kaj/ructe/compare/v0.14.0...v0.14.2)

---
updated-dependencies:
- dependency-name: ructe
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-22 04:11:39 +00:00
d4248df45a Use helper struct to reduce template parameters 2022-08-19 10:34:37 +02:00
4b5d962c2c Refactor count_repositories 2022-08-18 17:23:09 +03:00
dbbbdad3fa Allow providing a branch name in generator 2022-08-18 14:07:07 +02:00
12 changed files with 160 additions and 83 deletions

54
Cargo.lock generated
View File

@ -669,9 +669,9 @@ dependencies = [
[[package]]
name = "futures"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
checksum = "ab30e97ab6aacfe635fad58f22c2bb06c8b685f7421eb1e064a729e2a5f481fa"
dependencies = [
"futures-channel",
"futures-core",
@ -684,9 +684,9 @@ dependencies = [
[[package]]
name = "futures-channel"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
checksum = "2bfc52cbddcfd745bf1740338492bb0bd83d76c67b445f91c5fb29fae29ecaa1"
dependencies = [
"futures-core",
"futures-sink",
@ -694,15 +694,15 @@ dependencies = [
[[package]]
name = "futures-core"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
checksum = "d2acedae88d38235936c3922476b10fced7b2b68136f5e3c03c2d5be348a1115"
[[package]]
name = "futures-executor"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
checksum = "1d11aa21b5b587a64682c0094c2bdd4df0076c5324961a40cc3abd7f37930528"
dependencies = [
"futures-core",
"futures-task",
@ -711,15 +711,15 @@ dependencies = [
[[package]]
name = "futures-io"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
checksum = "93a66fc6d035a26a3ae255a6d2bca35eda63ae4c5512bef54449113f7a1228e5"
[[package]]
name = "futures-macro"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
checksum = "0db9cce532b0eae2ccf2766ab246f114b56b9cf6d445e00c2549fbc100ca045d"
dependencies = [
"proc-macro2",
"quote",
@ -728,21 +728,21 @@ dependencies = [
[[package]]
name = "futures-sink"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
checksum = "ca0bae1fe9752cf7fd9b0064c674ae63f97b37bc714d745cbde0afb7ec4e6765"
[[package]]
name = "futures-task"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
checksum = "842fc63b931f4056a24d59de13fb1272134ce261816e063e634ad0c15cdc5306"
[[package]]
name = "futures-util"
version = "0.3.21"
version = "0.3.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
checksum = "f0828a5471e340229c11c77ca80017937ce3c58cb788a17e5f1c2d5c485a9577"
dependencies = [
"futures-channel",
"futures-core",
@ -868,7 +868,7 @@ dependencies = [
[[package]]
name = "hoc"
version = "0.22.4"
version = "0.23.0"
dependencies = [
"actix-rt",
"actix-web",
@ -1640,9 +1640,9 @@ dependencies = [
[[package]]
name = "ructe"
version = "0.14.0"
version = "0.14.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef88d8c2492d7266e264b31e0ffcf1149d5ba183bccd3abaf1483ee905fc85de"
checksum = "ef279e568db5dad3a1867112fedc63e2f0567991e82beec01c04ade6bd53c08a"
dependencies = [
"base64 0.13.0",
"bytecount",
@ -1740,18 +1740,18 @@ checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c"
[[package]]
name = "serde"
version = "1.0.143"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.143"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
dependencies = [
"proc-macro2",
"quote",
@ -1760,9 +1760,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.83"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
dependencies = [
"itoa",
"ryu",

View File

@ -1,6 +1,6 @@
[package]
name = "hoc"
version = "0.22.4"
version = "0.23.0"
authors = ["Valentin Brandl <vbrandl@riseup.net>"]
edition = "2018"
build = "build.rs"
@ -19,16 +19,16 @@ badge = "0.3.0"
bytes = "1.2.1"
config = { version = "0.13.2", features = ["toml"] }
dotenv = "0.15.0"
futures = "0.3.21"
futures = "0.3.23"
git2 = "0.15.0"
lazy_static = "1.4.0"
mime = "0.3"
number_prefix = "0.4.0"
openssl-probe = "0.1.5"
reqwest = "0.11.11"
serde = "1.0.143"
serde = "1.0.144"
serde_derive = "1.0.137"
serde_json = "1.0.83"
serde_json = "1.0.85"
tracing = "0.1.36"
tracing-actix-web = "0.6.0"
tracing-bunyan-formatter = "0.3.3"
@ -37,11 +37,11 @@ tracing-log = "0.1.3"
tracing-subscriber = { version = "0.3.15", features = ["registry", "env-filter"] }
[build-dependencies]
ructe = { version = "0.14.0", features = ["mime03"] }
ructe = { version = "0.14.2", features = ["mime03"] }
vergen = { version = "7.3.1", default-features = false, features = ["git"] }
[dev-dependencies]
awc = "3.0.0"
ructe = "0.14.0"
ructe = "0.14.2"
tempfile = "3.3.0"
tokio = "1.20.1"

View File

@ -1,10 +1,13 @@
FROM ekidd/rust-musl-builder:stable as builder
# FROM ekidd/rust-musl-builder:stable as builder
FROM clux/muslrust:stable as builder
# create new cargo project
RUN USER=rust cargo init --lib
RUN cargo init --lib
# RUN USER=rust cargo init --lib
RUN echo 'fn main() { println!("Hello, world!"); }' >> src/main.rs
# copy build config
COPY --chown=rust ./Cargo.lock ./Cargo.lock
# COPY --chown=rust ./Cargo.lock ./Cargo.lock
COPY ./Cargo.lock ./Cargo.lock
COPY ./Cargo.toml ./Cargo.toml
# HACK: remove build-dependencies so we have at least some caching
RUN head -n $(($(grep -n "\[build-dependencies\]" Cargo.toml | cut -f1 -d:) - 1)) Cargo.toml | sed '/build.rs/d' > \
@ -38,6 +41,7 @@ USER hoc
# FROM scratch
# COPY --from=linuxkit/ca-certificates:v0.7 / /
COPY --from=builder /home/rust/src/target/x86_64-unknown-linux-musl/release/hoc .
# COPY --from=builder /home/rust/src/target/x86_64-unknown-linux-musl/release/hoc .
COPY --from=builder /volume/target/x86_64-unknown-linux-musl/release/hoc .
ENTRYPOINT ["/home/hoc/hoc"]

View File

@ -1,27 +1,30 @@
use crate::error::Result;
use std::{fs::read_dir, path::Path, result::Result as StdResult};
use std::{
fs::{read_dir, ReadDir},
iter::once,
path::Path,
result::Result as StdResult,
};
/// The on disk layout for served repos is `<service>/<user>/<repo>`
/// so to get the amount of repos, we just have to count everything
/// in `*/*/*` to get the count.
#[instrument]
pub(crate) fn count_repositories<P>(repo_path: P) -> Result<usize>
pub fn count_repositories<P>(repo_path: P) -> Result<usize>
where
P: AsRef<Path> + std::fmt::Debug,
{
trace!("Counting repositories");
std::fs::create_dir_all(&repo_path)?;
Ok(read_dir(repo_path)?
.filter_map(StdResult::ok)
.filter(|entry| entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false))
.map(|entry| read_dir(entry.path()))
.filter_map(StdResult::ok)
.flat_map(|dir| {
dir.filter_map(StdResult::ok)
.filter(|entry| entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false))
})
.map(|entry| read_dir(entry.path()))
.filter_map(StdResult::ok)
.flat_map(|dir| {
dir.filter_map(StdResult::ok)
.filter(|entry| entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false))
})
Ok(once(read_dir(repo_path)?)
.flat_map(sub_directories)
.flat_map(sub_directories)
.flat_map(sub_directories)
.count())
}
fn sub_directories(dir: ReadDir) -> impl Iterator<Item = ReadDir> {
dir.filter_map(StdResult::ok)
.filter(|entry| entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false))
.filter_map(|entry| read_dir(entry.path()).ok())
}

View File

@ -5,7 +5,7 @@ use std::fmt;
pub(crate) type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub(crate) enum Error {
pub enum Error {
Badge(String),
Client(reqwest::Error),
Git(git2::Error),

View File

@ -11,7 +11,7 @@ extern crate tracing;
mod cache;
pub mod config;
mod count;
pub mod count;
mod error;
mod service;
mod statics;
@ -24,7 +24,7 @@ use crate::{
error::{Error, Result},
service::{Bitbucket, FormService, GitHub, Gitlab, Service, Sourcehut},
statics::{CLIENT, VERSION_INFO},
template::RepoInfo,
template::{RepoGeneratorInfo, RepoInfo},
};
use actix_web::{
dev::Server,
@ -56,6 +56,7 @@ struct GeneratorForm<'a> {
service: FormService,
user: Cow<'a, str>,
repo: Cow<'a, str>,
branch: Option<Cow<'a, str>>,
}
#[derive(Debug)]
@ -438,16 +439,23 @@ async fn generate(
state: web::Data<State>,
repo_count: web::Data<AtomicUsize>,
) -> Result<HttpResponse> {
let repo = format!("{}/{}", params.user, params.repo);
let mut buf = Vec::new();
let repo_info = RepoGeneratorInfo {
service: params.service,
user: &params.user,
repo: &params.repo,
branch: params
.branch
.as_deref()
.filter(|s| !s.is_empty())
.unwrap_or("master"),
};
templates::generate(
&mut buf,
VERSION_INFO,
repo_count.load(Ordering::Relaxed),
&state.settings.base_url,
params.service.url(),
params.service.service(),
&repo,
&repo_info,
)?;
Ok(HttpResponse::Ok().content_type("text/html").body(buf))

View File

@ -28,8 +28,8 @@ pub(crate) trait Service: Sized + 'static {
}
}
#[derive(Deserialize, Serialize)]
pub(crate) enum FormService {
#[derive(Deserialize, Serialize, Clone, Copy)]
pub enum FormService {
#[serde(rename = "github")]
GitHub,
#[serde(rename = "gitlab")]

View File

@ -1,3 +1,5 @@
use crate::service::FormService;
pub struct RepoInfo<'a> {
pub commit_url: &'a str,
pub commits: u64,
@ -9,3 +11,10 @@ pub struct RepoInfo<'a> {
pub url: &'a str,
pub branch: &'a str,
}
pub struct RepoGeneratorInfo<'a> {
pub service: FormService,
pub user: &'a str,
pub repo: &'a str,
pub branch: &'a str,
}

View File

@ -1,16 +1,16 @@
@use super::base;
@use crate::statics::VersionInfo;
@use crate::{statics::VersionInfo, template::RepoGeneratorInfo};
@(version_info: VersionInfo, repo_count: usize, base_url: &str, url: &str, service: &str, path: &str)
@(version_info: VersionInfo, repo_count: usize, base_url: &str, repo_info: &RepoGeneratorInfo)
@:base("Hits-of-Code Badges", "Badge Generator", {
<p>
Here is the markdown for the badge for <a href="https://@url/@path">@url/@path</a>
Here is the markdown for the badge for <a href="https://@repo_info.service.url()/@repo_info.user/@repo_info.repo">@repo_info.user/@repo_info.repo</a>
</p>
<pre>
[![Hits-of-Code](@base_url/@service/@path)](@base_url/@service/@path/view)
[![Hits-of-Code](@base_url/@repo_info.service.service()/@repo_info.user/@repo_info.repo?branch=@repo_info.branch)](@base_url/@repo_info.service.service()/@repo_info.user/@repo_info.repo/view?branch=@repo_info.branch)
</pre>
<p>
@ -18,6 +18,6 @@ It will be rendered like this
</p>
<pre>
<a href="@base_url/@service/@path/view"><img src="@base_url/@service/@path" alt="example badge" /></a>
<a href="@base_url/@repo_info.service.service()/@repo_info.user/@repo_info.repo/view?branch=@repo_info.branch"><img src="@base_url/@repo_info.service.service()/@repo_info.user/@repo_info.repo?branch=@repo_info.branch" alt="example badge" /></a>
</pre>
}, version_info, repo_count)

View File

@ -80,6 +80,8 @@ the lines of
<input name="user" id="user" type="text" placeholder="user" />
<label>/</label>
<input name="repo" id="repo" type="text" placeholder="repository" />
<label>:</label>
<input name="branch" id="branch" type="text" placeholder="branch (defaults to `master`)" />
<button type="submit">Generate</button>
</form>

66
tests/count.rs Normal file
View File

@ -0,0 +1,66 @@
use hoc::count::count_repositories;
use tempfile::TempDir;
#[test]
fn no_repos() {
let repos = TempDir::new().unwrap();
assert_eq!(0, count_repositories(&repos).unwrap())
}
#[test]
fn no_repos_for_provider() {
let repos = TempDir::new().unwrap();
let _provider = TempDir::new_in(&repos).unwrap();
assert_eq!(0, count_repositories(&repos).unwrap())
}
#[test]
fn no_repos_for_owner() {
let repos = TempDir::new().unwrap();
let provider = TempDir::new_in(&repos).unwrap();
let _owner = TempDir::new_in(&provider).unwrap();
assert_eq!(0, count_repositories(&repos).unwrap())
}
#[test]
fn one_repo_for_owner() {
let repos = TempDir::new().unwrap();
let provider = TempDir::new_in(&repos).unwrap();
let owner = TempDir::new_in(&provider).unwrap();
let _repo = TempDir::new_in(&owner).unwrap();
assert_eq!(1, count_repositories(&repos).unwrap())
}
#[test]
fn two_repos_for_owner() {
let repos = TempDir::new().unwrap();
let provider = TempDir::new_in(&repos).unwrap();
let owner = TempDir::new_in(&provider).unwrap();
let _repo1 = TempDir::new_in(&owner).unwrap();
let _repo2 = TempDir::new_in(&owner).unwrap();
assert_eq!(2, count_repositories(&repos).unwrap())
}
#[test]
fn two_repos_for_two_providers() {
let repos = TempDir::new().unwrap();
let provider1 = TempDir::new_in(&repos).unwrap();
let owner1 = TempDir::new_in(&provider1).unwrap();
let _repo1 = TempDir::new_in(&owner1).unwrap();
let provider2 = TempDir::new_in(&repos).unwrap();
let owner2 = TempDir::new_in(&provider2).unwrap();
let _repo2 = TempDir::new_in(&owner2).unwrap();
assert_eq!(2, count_repositories(&repos).unwrap())
}
#[test]
fn two_subdirs_in_one_repo() {
let repos = TempDir::new().unwrap();
let provider = TempDir::new_in(&repos).unwrap();
let owner = TempDir::new_in(&provider).unwrap();
let repo = TempDir::new_in(&owner).unwrap();
let _subdir1 = TempDir::new_in(&repo).unwrap();
let _subdir2 = TempDir::new_in(&repo).unwrap();
assert_eq!(1, count_repositories(&repos).unwrap())
}

View File

@ -14,18 +14,3 @@ async fn favicon() {
assert!(response.status().is_success());
}
#[actix_rt::test]
async fn tacit_css() {
let test_app = util::spawn_app().await;
let client = awc::Client::default();
let response = client
.get(&format!("{}/tacit-css.min.css", test_app.address))
.send()
.await
.expect("Failed to execute request");
assert!(response.status().is_success());
}