REWRITE IT IN RUST #1

Merged
cadey merged 4 commits from riir into master 2020-05-28 19:42:11 +00:00
15 changed files with 1747 additions and 129 deletions

View File

@ -1,8 +1,42 @@
kind: pipeline
name: nix builds
name: nix build and push
steps:
- name: docker image
image: lnl7/nix:2020-03-07
image: "monacoremo/nix:2020-04-05-05f09348-circleci"
commands:
- nix-build docker.nix
- cp $(readlink result) /result/docker.tgz
volumes:
- name: result
path: /result
- name: push image
image: docker:dind
volumes:
- name: result
path: /result
- name: dockersock
path: /var/run
commands:
- docker load -i /result/docker.tgz
- echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin
- docker push xena/quickserv
environment:
DOCKER_USERNAME:
from_secret: DOCKER_USERNAME
DOCKER_PASSWORD:
from_secret: DOCKER_PASSWORD
services:
- name: docker
image: docker:dind
privileged: true
volumes:
- name: dockersock
path: /var/run
volumes:
- name: result
temp: {}
- name: dockersock
temp: {}

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/result-bin
/result
/target

1460
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

14
Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "quickserv"
version = "0.1.0"
authors = ["Christine Dodrill <me@christine.website>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0"
env_logger = "0.7"
structopt = "0.3"
tokio = { version = "0.2", features = ["macros"] }
warp = "0.2"

View File

@ -1,13 +1,40 @@
# quickserv
[![built with
nix](https://builtwithnix.org/badge.svg)](https://builtwithnix.org) [![Build
Status](https://drone.tulpa.dev/api/badges/Xe/quickserv/status.svg)](https://drone.tulpa.dev/Xe/quickserv)
[![Written in Rust](https://img.shields.io/badge/written%20in-Rust-orange)](https://www.rust-lang.org/)
A quick HTTP server for when you have given up on life.
`quickserv` serves `.` on port `3000`. Customizable with flags:
```
Usage of quickserv:
-dir string
directory to serve (default ".")
-port string
port to use (default "3000")
quickserv 0.1.0
A quick HTTP fileserver
USAGE:
quickserv [OPTIONS]
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-d, --dir <dir> [env: DIR=] [default: .]
-p, --port <port> [env: PORT=] [default: 3000]
```
## Docker
```console
$ nix-build docker.nix
$ docker load -f result
$ docker push xena/quickserv
```
## Release
- Bump the version in `Cargo.toml`
- Rerun CI
- Tag a new release

View File

@ -1,16 +1,13 @@
{ pkgs ? import <nixpkgs> {} }:
{ pkgs ? import <nixpkgs> { }, sources ? import ./nix/sources.nix
, naersk ? import sources.naersk { } }:
with pkgs;
buildGoPackage rec {
name = "quickserv";
version = "1.0.0";
goPackagePath = "tulpa.dev/Xe/quickserv";
src = ./.;
goDeps = ./deps.nix;
preBuild = ''
export CGO_ENABLED=0
buildFlagsArray+=(-pkgdir "$TMPDIR")
'';
allowGoReference = false;
}
let
srcNoTarget = dir:
builtins.filterSource
(path: type: type != "directory" || builtins.baseNameOf path != "target")
dir;
naersk = pkgs.callPackage sources.naersk { };
src = srcNoTarget ./.;
remapPathPrefix = true;
in naersk.buildPackage { inherit src remapPathPrefix; }

View File

@ -1,57 +0,0 @@
# file generated from go.mod using vgo2nix (https://github.com/adisbladis/vgo2nix)
[
{
goPackagePath = "github.com/davecgh/go-spew";
fetch = {
type = "git";
url = "https://github.com/davecgh/go-spew";
rev = "v1.1.1";
sha256 = "0hka6hmyvp701adzag2g26cxdj47g21x6jz4sc6jjz1mn59d474y";
};
}
{
goPackagePath = "github.com/facebookarchive/flagenv";
fetch = {
type = "git";
url = "https://github.com/facebookarchive/flagenv";
rev = "fcd59fca7456";
sha256 = "0c7fw4y4gmdrn66dx7la637lx0hvs1w27x9j12wdx037n51r078g";
};
}
{
goPackagePath = "github.com/facebookgo/ensure";
fetch = {
type = "git";
url = "https://github.com/facebookgo/ensure";
rev = "63f1cf65ac4c";
sha256 = "05vi49g2967i5awcb1z69i2n5b5hwn06682kw90x81hbxlr0px36";
};
}
{
goPackagePath = "github.com/facebookgo/flagenv";
fetch = {
type = "git";
url = "https://github.com/facebookgo/flagenv";
rev = "fcd59fca7456";
sha256 = "0c7fw4y4gmdrn66dx7la637lx0hvs1w27x9j12wdx037n51r078g";
};
}
{
goPackagePath = "github.com/facebookgo/stack";
fetch = {
type = "git";
url = "https://github.com/facebookgo/stack";
rev = "751773369052";
sha256 = "07yr05mz7h007ldpij90zjflwgixp148sbyrdlh1fj5bikr4p8m3";
};
}
{
goPackagePath = "github.com/facebookgo/subset";
fetch = {
type = "git";
url = "https://github.com/facebookgo/subset";
rev = "c811ad88dec4";
sha256 = "1sjczgmq26mgqvh7267saypnn4sfdjx467wsm1pgdhyss77mc650";
};
}
]

View File

@ -3,12 +3,12 @@
let
pkgs = import <nixpkgs> { };
callPackage = pkgs.lib.callPackageWith pkgs;
printerfacts = callPackage ./default.nix { };
quickserv = callPackage ./default.nix { };
dockerImage = pkg:
pkgs.dockerTools.buildLayeredImage {
name = "xena/quickserv";
tag = "latest";
tag = "${quickserv.version}";
contents = [ pkg ];
@ -18,4 +18,4 @@ let
};
};
in dockerImage printerfacts
in dockerImage quickserv

12
go.mod
View File

@ -1,12 +0,0 @@
module tulpa.dev/Xe/quickserv
go 1.13
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/facebookarchive/flagenv v0.0.0-20160425205200-fcd59fca7456
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect
github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456 // indirect
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect
)

12
go.sum
View File

@ -1,12 +0,0 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/facebookarchive/flagenv v0.0.0-20160425205200-fcd59fca7456 h1:1NzATV1A9LeTWAuAJGd7vE/wYSO08EJQTrwKcBBR6Cw=
github.com/facebookarchive/flagenv v0.0.0-20160425205200-fcd59fca7456/go.mod h1:Lbo+w7sC1xznzryrqUDoBBT2nLKV9JnDOzdiVMHYX/8=
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0=
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456 h1:CkmB2l68uhvRlwOTPrwnuitSxi/S3Cg4L5QYOcL9MBc=
github.com/facebookgo/flagenv v0.0.0-20160425205200-fcd59fca7456/go.mod h1:zFhibDvPDWmtk4dAQ05sRobtyoffEHygEt3wSNuAzz8=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk=
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=

23
main.go
View File

@ -1,23 +0,0 @@
// Command quickserv serves a folder of files over HTTP quickly.
package main
import (
"flag"
"log"
"net/http"
"github.com/facebookarchive/flagenv"
)
var (
port = flag.String("port", "3000", "port to use")
dir = flag.String("dir", ".", "directory to serve")
)
func main() {
flagenv.Parse()
flag.Parse()
http.Handle("/", http.FileServer(http.Dir(*dir)))
log.Printf("Serving %s on port %s", *dir, *port)
log.Fatal(http.ListenAndServe(":"+*port, nil))
}

14
nix/sources.json Normal file
View File

@ -0,0 +1,14 @@
{
"naersk": {
"branch": "master",
"description": "Build rust crates in Nix. No configuration, no code generation, no IFD. Sandbox friendly.",
"homepage": "",
"owner": "nmattia",
"repo": "naersk",
"rev": "a82fd7dc31a58c462b6dfa9d9d886fa2cc75dfd4",
"sha256": "00bjwir52y6jbf0b22qy9qxramw35k5fc7kp9hymr1zgpmw9kbwg",
"type": "tarball",
"url": "https://github.com/nmattia/naersk/archive/a82fd7dc31a58c462b6dfa9d9d886fa2cc75dfd4.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}
}

134
nix/sources.nix Normal file
View File

@ -0,0 +1,134 @@
# This file has been generated by Niv.
let
#
# The fetchers. fetch_<type> fetches specs of type <type>.
#
fetch_file = pkgs: spec:
if spec.builtin or true then
builtins_fetchurl { inherit (spec) url sha256; }
else
pkgs.fetchurl { inherit (spec) url sha256; };
fetch_tarball = pkgs: spec:
if spec.builtin or true then
builtins_fetchTarball { inherit (spec) url sha256; }
else
pkgs.fetchzip { inherit (spec) url sha256; };
fetch_git = spec:
builtins.fetchGit { url = spec.repo; inherit (spec) rev ref; };
fetch_builtin-tarball = spec:
builtins.trace
''
WARNING:
The niv type "builtin-tarball" will soon be deprecated. You should
instead use `builtin = true`.
$ niv modify <package> -a type=tarball -a builtin=true
''
builtins_fetchTarball { inherit (spec) url sha256; };
fetch_builtin-url = spec:
builtins.trace
''
WARNING:
The niv type "builtin-url" will soon be deprecated. You should
instead use `builtin = true`.
$ niv modify <package> -a type=file -a builtin=true
''
(builtins_fetchurl { inherit (spec) url sha256; });
#
# Various helpers
#
# The set of packages used when specs are fetched using non-builtins.
mkPkgs = sources:
let
sourcesNixpkgs =
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) {};
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
in
if builtins.hasAttr "nixpkgs" sources
then sourcesNixpkgs
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
import <nixpkgs> {}
else
abort
''
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
add a package called "nixpkgs" to your sources.json.
'';
# The actual fetching function.
fetch = pkgs: name: spec:
if ! builtins.hasAttr "type" spec then
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
else if spec.type == "file" then fetch_file pkgs spec
else if spec.type == "tarball" then fetch_tarball pkgs spec
else if spec.type == "git" then fetch_git spec
else if spec.type == "builtin-tarball" then fetch_builtin-tarball spec
else if spec.type == "builtin-url" then fetch_builtin-url spec
else
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
# Ports of functions for older nix versions
# a Nix version of mapAttrs if the built-in doesn't exist
mapAttrs = builtins.mapAttrs or (
f: set: with builtins;
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
);
# fetchTarball version that is compatible between all the versions of Nix
builtins_fetchTarball = { url, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchTarball;
in
if lessThan nixVersion "1.12" then
fetchTarball { inherit url; }
else
fetchTarball attrs;
# fetchurl version that is compatible between all the versions of Nix
builtins_fetchurl = { url, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchurl;
in
if lessThan nixVersion "1.12" then
fetchurl { inherit url; }
else
fetchurl attrs;
# Create the final "sources" from the config
mkSources = config:
mapAttrs (
name: spec:
if builtins.hasAttr "outPath" spec
then abort
"The values in sources.json should not have an 'outPath' attribute"
else
spec // { outPath = fetch config.pkgs name spec; }
) config.sources;
# The "config" used by the fetchers
mkConfig =
{ sourcesFile ? ./sources.json
, sources ? builtins.fromJSON (builtins.readFile sourcesFile)
, pkgs ? mkPkgs sources
}: rec {
# The sources, i.e. the attribute set of spec name to spec
inherit sources;
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
inherit pkgs;
};
in
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }

View File

@ -1,2 +1,17 @@
let pkgs = import <nixpkgs> { };
in pkgs.mkShell { buildInputs = with pkgs; [ go vgo2nix ]; }
in pkgs.mkShell {
buildInputs = with pkgs; [
# go
go
goimports
nur.repos.xe.gopls
vgo2nix
# rust
cargo
cargo-watch
rls
rustc
rustfmt
];
}

26
src/main.rs Normal file
View File

@ -0,0 +1,26 @@
use std::path::PathBuf;
use structopt::StructOpt;
/// A quick HTTP fileserver
#[derive(StructOpt, Debug)]
#[structopt(name = "quickserv")]
struct Opt {
// The HTTP port to listen on
#[structopt(short, long, env="PORT", default_value="3000")]
port: u16,
// The path to serve
#[structopt(short, long, env="DIR", default_value=".")]
dir: PathBuf,
}
#[tokio::main]
async fn main() {
env_logger::init();
let opt = Opt::from_args();
log::info!("serving {:?} on port {}", opt.dir, opt.port);
warp::serve(warp::fs::dir(opt.dir))
.run(([0, 0, 0, 0], opt.port))
.await;
}