зеркало из https://github.com/github/libprojfs.git
Docker helpers
This commit is contained in:
Родитель
95fe613b11
Коммит
286996b52c
|
@ -0,0 +1,3 @@
|
|||
[submodule "docker/VFSForGit"]
|
||||
path = docker/VFSForGit
|
||||
url = https://github.com/github/VFSForGit.git
|
|
@ -0,0 +1,7 @@
|
|||
language: ruby
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
script:
|
||||
- docker/cibuild
|
|
@ -0,0 +1,21 @@
|
|||
FROM github/fuse3-linux
|
||||
|
||||
LABEL org.label-schema.name="projfs-develop"
|
||||
LABEL org.label-schema.description="projfs Linux libprojfs development image"
|
||||
LABEL org.label-schema.vendor="GitHub"
|
||||
LABEL org.label-schema.schema-version="1.0"
|
||||
|
||||
WORKDIR /data/projfs
|
||||
|
||||
RUN set -ex && \
|
||||
apt-get update -qq && \
|
||||
BUILD_DEPS=' \
|
||||
automake \
|
||||
build-essential \
|
||||
libtool \
|
||||
' && \
|
||||
apt-get install -y -qq --no-install-recommends $BUILD_DEPS && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG UID
|
||||
RUN useradd -d /data -M -s /bin/bash -u $UID -G 0 user
|
|
@ -0,0 +1,58 @@
|
|||
FROM github/fuse3-linux
|
||||
|
||||
LABEL org.label-schema.name="projfs-distpkg"
|
||||
LABEL org.label-schema.description="projfs Linux libprojfs distribution image"
|
||||
LABEL org.label-schema.vendor="GitHub"
|
||||
LABEL org.label-schema.schema-version="1.0"
|
||||
|
||||
ARG PROJFS_REPO=projfs-linux-private
|
||||
|
||||
ENV BUILD_DEPS ' \
|
||||
automake \
|
||||
build-essential \
|
||||
dpkg-dev \
|
||||
libtool \
|
||||
pkg-config \
|
||||
'
|
||||
|
||||
RUN apt-get update -qq && \
|
||||
apt-get install -y -qq --no-install-recommends $BUILD_DEPS && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY repos/$PROJFS_REPO /tmp/$PROJFS_REPO
|
||||
|
||||
WORKDIR /tmp/$PROJFS_REPO
|
||||
RUN ./autogen.sh
|
||||
RUN make -j "$(nproc)" distclean
|
||||
RUN ./configure --enable-vfs-api
|
||||
RUN make -j "$(nproc)" dist
|
||||
|
||||
WORKDIR /tmp
|
||||
RUN \
|
||||
PROJFS_VERSION=$(pkg-config --modversion $PROJFS_REPO/projfs.pc) && \
|
||||
PROJFS_RELEASE="libprojfs-$PROJFS_VERSION" && \
|
||||
PROJFS_DISTPKG="$PROJFS_RELEASE.tar.xz" && \
|
||||
\
|
||||
tar -xJf "$PROJFS_REPO/$PROJFS_DISTPKG" && \
|
||||
rm -rf "$PROJFS_REPO" && \
|
||||
mv "$PROJFS_RELEASE" libprojfs-release
|
||||
|
||||
WORKDIR /tmp/libprojfs-release
|
||||
RUN \
|
||||
DEB_HOST_MULTIARCH="$(dpkg-architecture --query DEB_HOST_MULTIARCH)" && \
|
||||
./configure --prefix=/usr \
|
||||
--libdir="\${prefix}/lib/$DEB_HOST_MULTIARCH" \
|
||||
--libexecdir="\${prefix}/lib/$DEB_HOST_MULTIARCH" \
|
||||
--sysconfdir=/etc \
|
||||
--disable-static \
|
||||
--enable-shared \
|
||||
--enable-vfs-api
|
||||
RUN make -j "$(nproc)" install
|
||||
|
||||
WORKDIR /tmp
|
||||
RUN \
|
||||
DEB_HOST_MULTIARCH="$(dpkg-architecture --query DEB_HOST_MULTIARCH)" && \
|
||||
rm -rf /tmp/libprojfs-release && \
|
||||
rm -f /usr/lib/$DEB_HOST_MULTIARCH/libprojfs.la
|
||||
|
||||
RUN apt-get purge -y --auto-remove $BUILD_DEPS
|
|
@ -0,0 +1,36 @@
|
|||
FROM debian:stretch
|
||||
|
||||
LABEL org.label-schema.name="projfs-fuse3"
|
||||
LABEL org.label-schema.description="projfs Linux libfuse v3 image"
|
||||
LABEL org.label-schema.vendor="GitHub"
|
||||
LABEL org.label-schema.schema-version="1.0"
|
||||
|
||||
ARG FUSE_VERSION=3.3.0
|
||||
ARG FUSE_SHA256=c554863405477cd138c38944be9cdc3781a51d78c369ab878083feb256111b65
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
# fuse3 requires meson 0.42, available from stretch-backports
|
||||
# wget depends on ca-certificates
|
||||
|
||||
RUN \
|
||||
echo 'deb http://deb.debian.org/debian stretch-backports main' >> /etc/apt/sources.list.d/stretch-backports.list && \
|
||||
apt-get update -qq && \
|
||||
apt-get install -y -qq --no-install-recommends build-essential ca-certificates pkg-config wget udev && \
|
||||
apt-get install -y -qq --no-install-recommends -t=stretch-backports meson && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV FUSE_RELEASE "fuse-$FUSE_VERSION"
|
||||
ENV FUSE_DOWNLOAD "$FUSE_RELEASE.tar.xz"
|
||||
ENV FUSE_URL_PATH "releases/download/$FUSE_RELEASE/$FUSE_DOWNLOAD"
|
||||
|
||||
RUN \
|
||||
wget -q "https://github.com/libfuse/libfuse/$FUSE_URL_PATH" && \
|
||||
echo "$FUSE_SHA256 $FUSE_DOWNLOAD" | sha256sum -c -
|
||||
|
||||
RUN tar -xJf "$FUSE_DOWNLOAD"
|
||||
WORKDIR "$FUSE_RELEASE/build"
|
||||
|
||||
RUN meson --prefix=/usr --sysconfdir=/etc --localstatedir=/var ..
|
||||
RUN ninja -j "$(nproc)"
|
||||
RUN ninja install
|
|
@ -0,0 +1,19 @@
|
|||
FROM microsoft/dotnet:2.2-sdk-stretch
|
||||
|
||||
ARG FUSE_VERSION=3.3.0
|
||||
|
||||
WORKDIR /data/integrate
|
||||
ENV HOME /data/integrate
|
||||
|
||||
COPY --from=github/fuse3-linux \
|
||||
/usr/lib/x86_64-linux-gnu/libfuse3.so.$FUSE_VERSION \
|
||||
/usr/lib/x86_64-linux-gnu/
|
||||
|
||||
RUN set -ex && \
|
||||
cd /usr/lib/x86_64-linux-gnu && \
|
||||
ln -s libfuse3.so.$FUSE_VERSION libfuse3.so.3 && \
|
||||
ln -s libfuse3.so.3 libfuse3.so
|
||||
|
||||
# Allow VFSforGit to load locally-compiled libprojfs binaries for development
|
||||
ENV LD_LIBRARY_PATH /data/projfs/lib/.libs
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
FROM microsoft/dotnet:2.2-sdk-stretch
|
||||
|
||||
WORKDIR /data/vfs/src
|
||||
ENV HOME /data
|
||||
RUN chmod 0777 /data
|
|
@ -0,0 +1,136 @@
|
|||
# projfs-docker
|
||||
|
||||
Build projfs with Docker.
|
||||
|
||||
- [Getting started](#getting-started)
|
||||
- [How it works](#how-it-works)
|
||||
|
||||
## Getting started
|
||||
|
||||
``` console
|
||||
$ ./projfs
|
||||
usage: ./projfs [command]
|
||||
|
||||
command:
|
||||
setup
|
||||
Build all containers and run all build scripts necessary for
|
||||
development work (excludes distpkg).
|
||||
|
||||
image fuse3|develop|distpkg|vfs|integrate
|
||||
Build the Docker build environment for the specified component.
|
||||
|
||||
develop configure|make|test|dist|clean
|
||||
Builds libprojfs for local development and testing.
|
||||
|
||||
configure: runs autogen with appropriate switches
|
||||
make: runs make
|
||||
test: runs make test
|
||||
dist: runs make dist
|
||||
clean: runs make clean
|
||||
|
||||
vfs restore|make
|
||||
Build VFSForGit.
|
||||
|
||||
restore: do a NuGet restore
|
||||
make: build everything
|
||||
|
||||
integrate clone|mount
|
||||
Run the integration.
|
||||
|
||||
clone: run the MirrorProvider clone
|
||||
mount: mount the MirrorProvider
|
||||
|
||||
run IMAGE [OPTION ...] -- CMD [ARG ...]
|
||||
Run a command in the specified image (`fuse3', `develop', `vfs', etc.)
|
||||
Everything up until `--' is passed as options to `docker run', i.e.
|
||||
before the image name is given. If no options are specified, defaults
|
||||
for the image will be used (e.g. enables FUSE for the 'integrate'
|
||||
image).
|
||||
|
||||
exec IMAGE [OPTION ...] -- CMD [ARG ...]
|
||||
Run a command in a container already started with `./projfs run'.
|
||||
|
||||
test [--force]
|
||||
Run the test suite. Will fail if there's already a running integration
|
||||
container, unless --force is specified, in which case the running
|
||||
container is stopped before tests are run.
|
||||
```
|
||||
|
||||
Here's how to get started:
|
||||
|
||||
``` shell
|
||||
# Build all images, and run all build scripts. After this finishes, build
|
||||
# artifacts will be present in your local tree.
|
||||
./projfs setup
|
||||
|
||||
# Clone the test repository (found at build/PathToMirror). The created
|
||||
# repository will be at build/integrate/TestRoot.
|
||||
./projfs integrate clone
|
||||
|
||||
# Run the built-in end-to-end test suite (will clean up after itself if
|
||||
# successful).
|
||||
./projfs test
|
||||
|
||||
# Mount the test root.
|
||||
./projfs integrate mount
|
||||
|
||||
# In another terminal, interact with the created mount.
|
||||
./projfs exec integrate -- touch TestRoot/src/xyz
|
||||
./projfs exec integrate -- rm TestRoot/src/xyz
|
||||
|
||||
# Start a shell to play more. (pass `-t' to `docker exec')
|
||||
./projfs exec integrate -t -- bash
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
The command `./projfs image COMPONENT` will build one of five tagged Docker images.
|
||||
|
||||
- `./projfs image fuse3` creates `github/fuse3-linux` from `Dockerfile-fuse3`. It installs development tools and build
|
||||
prerequisites in a stock Debian stretch image, then fetches and builds FUSE 3.3.0.
|
||||
|
||||
- `./projfs image develop` creates `github/projfs-dev-linux` from `Dockerfile-develop`. It is based on
|
||||
`github/fuse3-linux`, and installs only the build tools necessary for building libprojfs.
|
||||
|
||||
- `./projfs image distpkg` creates `github/projfs-dist-linux` from `Dockerfile-distpkg`. It is based on
|
||||
`github/fuse3-linux`. The Dockerfile builds the dist package for libprojfs, then installs it. The resulting image
|
||||
represents what a clean system with the libprojfs dist package installed should look like.
|
||||
|
||||
- `./projfs image vfs` creates `github/vfs-linux` from `Dockerfile-vfs`. Right now this image is a plain
|
||||
Microsoft-supplied .NET SDK image with light filesystem modifications for testing.
|
||||
|
||||
- `./projfs image integrate` creates `github/projfs-vfs-linux` from `Dockerfile-integrate`. It uses the .NET SDK image
|
||||
as base, then copies the built FUSE objects from `github/fuse3-linux` and sets up the environment so libraries from
|
||||
the ProjFS build (when mounted) will be located correctly.
|
||||
|
||||
Note that each image is only a build environment, and does not contain any source code. Each component has a range of
|
||||
subcommands which will run commands in containers from each of these images; when doing so, `./projfs` mounts
|
||||
directories on the Docker host (your local filesystem) into the running containers, so that up-to-date source is seen
|
||||
and build artifacts are preserved.
|
||||
|
||||
The `projfs` component will mount the root of this repository at `/data/projfs` in the container. `./projfs develop
|
||||
configure` will run `/data/projfs/autogen.sh` in the container, with the output files being placed on the Docker host.
|
||||
`./projfs develop make` will then run `make`, with all build artifacts again placed on the Docker host. (You'll have a
|
||||
bunch of ELF objects which you won't be able to do anything with on macOS.)
|
||||
|
||||
The `vfs` component mounts the source at `/data/vfs/src`, and additional directories in `build` so that NuGet restored
|
||||
packages and all build output are preserved on the Docker host.
|
||||
|
||||
Finally, the `integrate` component mounts all of the above plus one more (the destination of the MirrorProvider clone
|
||||
operation), in locations such that everything Just Works™. Build artifacts from each of the previous steps are seen in
|
||||
the integration container, and paths and environment variables are set appropriately for the whole stack to function.
|
||||
|
||||
Note the filesystem layering that occurs when actually running the integration:
|
||||
|
||||
- `./projfs integrate clone` runs the MirrorProvider clone script, cloning `/data/PathToMirror` (`build/PathToMirror`)
|
||||
to `/data/integrate/TestRoot` (`build/integrate/TestRoot`). The source and destination of the clone are different
|
||||
Docker-mounted paths, i.e. both are on your local disk.
|
||||
|
||||
- `./projfs integrate mount` runs the MirrorProvider mount script on `/data/integrate/TestRoot`. `/data/integrate` is
|
||||
a mount from the host path `build/integrate` in this repo, so the `TestRoot` scaffolding created by the clone
|
||||
operation still exists. We then mount `/data/integrate/TestRoot/src`. This mount happens in the Docker container,
|
||||
meaning the container itself accessing `/data/integrate/TestRoot/src` will interact with FUSE. Meanwhile,
|
||||
`build/integrate/TestRoot/src` will appear as an empty directory on the Docker host.
|
||||
|
||||
We do this to allow rapid iteration without having to rebuild entire containers every time, which is required if the
|
||||
entire container build process also builds the project.
|
|
@ -0,0 +1 @@
|
|||
Subproject commit bc71f5de7b363c0b56b30be29e79ed1b9949b697
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
./projfs image fuse3
|
||||
|
||||
./projfs image develop
|
||||
./projfs develop configure
|
||||
./projfs develop make
|
||||
./projfs develop test
|
||||
|
||||
./projfs image vfs
|
||||
./projfs vfs restore
|
||||
./projfs vfs make
|
||||
|
||||
./projfs image integrate
|
||||
./projfs integrate clone
|
||||
./projfs test --force
|
|
@ -0,0 +1,80 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class Project
|
||||
def initialize(name, dockerfile:, image:, mounts: [], commands: {}, run_as_root: false, build_options: [], options: nil)
|
||||
@name = name
|
||||
@dockerfile = File.join(File.expand_path(File.dirname(__FILE__)), dockerfile)
|
||||
@image = image
|
||||
@mounts = mounts
|
||||
@commands = commands
|
||||
@run_as_root = run_as_root
|
||||
@build_options = build_options
|
||||
@options = options
|
||||
end
|
||||
|
||||
def build(quiet: true)
|
||||
raise "cannot build #@name" if ![@dockerfile, @image].all?
|
||||
system("docker", "build", *(quiet ? ["-q"] : []), *@build_options, "-f", @dockerfile, "-t", @image, File.dirname(__FILE__))
|
||||
end
|
||||
|
||||
def command(name, popen: false)
|
||||
raise "cannot run command for #@name" if !@image
|
||||
commands = @commands[name.intern] or raise "command #{name} not found for #@name"
|
||||
commands = [commands] if commands[0].is_a?(String)
|
||||
|
||||
if popen
|
||||
raise "cannot popen multiple commands" if commands.length > 1
|
||||
run("--", *commands[0], popen: true)
|
||||
else
|
||||
commands.each do |command|
|
||||
run("--", *command)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def run(*cmd, popen: false)
|
||||
raise "cannot run #@name" if !@image
|
||||
argv = []
|
||||
argv.concat(@options) if @options && (cmd.length == 0 || cmd[0] == '--')
|
||||
while cmd.any? && cmd[0] != '--'
|
||||
argv << cmd.shift
|
||||
end
|
||||
@mounts.each { |m| argv << "-v" << m }
|
||||
argv << @image
|
||||
cmd.shift if cmd[0] == '--'
|
||||
argv.concat(cmd)
|
||||
|
||||
args = ["docker", "run", *user_args, "--pid=host", "--rm", "--name", docker_container_name, *argv]
|
||||
if popen
|
||||
IO.popen(args, "r+", err: [:child, :out])
|
||||
else
|
||||
system(*args)
|
||||
end
|
||||
end
|
||||
|
||||
def exec(*cmd)
|
||||
raise "cannot exec #@name" if !@image
|
||||
argv = []
|
||||
while cmd.any? && cmd[0] != '--'
|
||||
argv << cmd.shift
|
||||
end
|
||||
argv << docker_container_name
|
||||
cmd.shift if cmd[0] == '--'
|
||||
argv.concat(cmd)
|
||||
system("docker", "exec", *user_args, "-i", *argv)
|
||||
end
|
||||
|
||||
def docker_container_name
|
||||
"projfs-#@name"
|
||||
end
|
||||
|
||||
def user_args
|
||||
if @run_as_root
|
||||
[]
|
||||
else
|
||||
["-u", Process.uid.to_s]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# vim: set sw=2 et:
|
|
@ -0,0 +1,201 @@
|
|||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'project'
|
||||
require_relative 'tests'
|
||||
|
||||
Dir.chdir(File.dirname(__FILE__))
|
||||
|
||||
def usage
|
||||
STDERR.puts <<~USAGE
|
||||
usage: #$0 [command]
|
||||
|
||||
command:
|
||||
setup
|
||||
Build all containers and run all build scripts necessary for
|
||||
development work (excludes distpkg).
|
||||
|
||||
image fuse3|develop|distpkg|vfs|integrate
|
||||
Build the Docker build environment for the specified component.
|
||||
|
||||
develop configure|make|test|dist|clean
|
||||
Builds libprojfs for local development and testing.
|
||||
|
||||
configure: runs autogen with appropriate switches
|
||||
make: runs make
|
||||
test: runs make test
|
||||
dist: runs make dist
|
||||
clean: runs make clean
|
||||
|
||||
vfs restore|make
|
||||
Build VFSForGit.
|
||||
|
||||
restore: do a NuGet restore
|
||||
make: build everything
|
||||
|
||||
integrate clone|mount
|
||||
Run the integration.
|
||||
|
||||
clone: run the MirrorProvider clone
|
||||
mount: mount the MirrorProvider
|
||||
|
||||
run IMAGE [OPTION ...] -- CMD [ARG ...]
|
||||
Run a command in the specified image (`fuse3', `develop', `vfs', etc.)
|
||||
Everything up until `--' is passed as options to `docker run', i.e.
|
||||
before the image name is given. If no options are specified, defaults
|
||||
for the image will be used (e.g. enables FUSE for the 'integrate'
|
||||
image).
|
||||
|
||||
exec IMAGE [OPTION ...] -- CMD [ARG ...]
|
||||
Run a command in a container already started with `#$0 run'.
|
||||
|
||||
test [--force]
|
||||
Run the test suite. Will fail if there's already a running integration
|
||||
container, unless --force is specified, in which case the running
|
||||
container is stopped before tests are run.
|
||||
USAGE
|
||||
exit 1
|
||||
end
|
||||
|
||||
def system(*args)
|
||||
puts ">> #{args.join " "}"
|
||||
result = Kernel.system(*args)
|
||||
if !result
|
||||
raise "failed to run '#{args.join " "}"
|
||||
end
|
||||
end
|
||||
|
||||
usage if ARGV.length == 0
|
||||
|
||||
fuse3 = Project.new('fuse3',
|
||||
dockerfile: 'Dockerfile-fuse3',
|
||||
image: 'github/fuse3-linux'
|
||||
)
|
||||
|
||||
develop = Project.new('develop',
|
||||
dockerfile: 'Dockerfile-develop',
|
||||
image: 'github/projfs-dev-linux',
|
||||
mounts: ["#{Dir.pwd}/..:/data/projfs"],
|
||||
commands: {
|
||||
configure: ['./autogen.sh', '--enable-vfs-api'],
|
||||
make: ['make'],
|
||||
test: ['make', 'test'],
|
||||
dist: ['make', 'dist'],
|
||||
clean: ['make', 'clean'],
|
||||
},
|
||||
build_options: ['--build-arg', "UID=#{Process.uid}"],
|
||||
options: ['--device', '/dev/fuse', '--cap-add', 'SYS_ADMIN'])
|
||||
|
||||
distpkg = Project.new('distpkg',
|
||||
dockerfile: 'Dockerfile-distpkg',
|
||||
image: 'github/projfs-dist-linux',
|
||||
mounts: ["#{Dir.pwd}/..:/data/projfs"]
|
||||
)
|
||||
|
||||
vfs = Project.new('vfs',
|
||||
dockerfile: 'Dockerfile-vfs',
|
||||
image: 'github/vfs-linux',
|
||||
mounts: [
|
||||
"#{Dir.pwd}/VFSForGit:/data/vfs/src",
|
||||
"#{Dir.pwd}/build/packages:/data/vfs/packages",
|
||||
"#{Dir.pwd}/build/BuildOutput:/data/vfs/BuildOutput",
|
||||
],
|
||||
commands: {
|
||||
restore: [
|
||||
["dotnet", "restore", "MirrorProvider/MirrorProvider.sln", "/p:Configuration=Debug.Linux", "--packages", "../packages"],
|
||||
["dotnet", "restore", "ProjFS.Linux/PrjFSLib.Linux.Managed/PrjFSLib.Linux.Managed.csproj", "/p:Configuration=Debug", "/p:Platform=x64", "--packages", "../packages"],
|
||||
],
|
||||
make: [
|
||||
["dotnet", "build", "ProjFS.Linux/PrjFSLib.Linux.Managed/PrjFSLib.Linux.Managed.csproj", "/p:Configuration=Debug", "/p:Platform=x64", "--no-restore"],
|
||||
["dotnet", "build", "MirrorProvider/MirrorProvider.sln", "/p:Configuration=Debug.Linux", "--no-restore"],
|
||||
]
|
||||
})
|
||||
|
||||
integrate = Project.new('integrate',
|
||||
dockerfile: 'Dockerfile-integrate',
|
||||
image: 'github/projfs-vfs-linux',
|
||||
mounts: [
|
||||
"#{Dir.pwd}/..:/data/projfs",
|
||||
"#{Dir.pwd}/VFSForGit:/data/vfs/src",
|
||||
"#{Dir.pwd}/build/packages:/data/vfs/packages",
|
||||
"#{Dir.pwd}/build/BuildOutput:/data/vfs/BuildOutput",
|
||||
"#{Dir.pwd}/build/PathToMirror:/data/PathToMirror",
|
||||
"#{Dir.pwd}/build/integrate:/data/integrate"
|
||||
],
|
||||
commands: {
|
||||
clone: [["env", "PATH_TO_MIRROR=/data/PathToMirror", "TEST_ROOT=/data/integrate/TestRoot", "/data/vfs/src/MirrorProvider/Scripts/Linux/MirrorProvider_Clone.sh"]],
|
||||
mount: [["env", "TEST_ROOT=/data/integrate/TestRoot", "/data/vfs/src/MirrorProvider/Scripts/Linux/MirrorProvider_Mount.sh"]],
|
||||
},
|
||||
options: ['--device', '/dev/fuse', '--cap-add', 'SYS_ADMIN', '-i'],
|
||||
run_as_root: true)
|
||||
|
||||
images = {
|
||||
"fuse3" => fuse3,
|
||||
"develop" => develop,
|
||||
"distpkg" => distpkg,
|
||||
"vfs" => vfs,
|
||||
"integrate" => integrate,
|
||||
}
|
||||
|
||||
case ARGV.shift
|
||||
when "setup"
|
||||
usage if ARGV.length > 0
|
||||
fuse3.build(quiet:false)
|
||||
|
||||
develop.build(quiet: false)
|
||||
develop.command "configure"
|
||||
develop.command "make"
|
||||
develop.command "test"
|
||||
|
||||
vfs.build(quiet: false)
|
||||
vfs.command "restore"
|
||||
vfs.command "make"
|
||||
|
||||
integrate.build(quiet: false)
|
||||
|
||||
when "image"
|
||||
usage if ARGV.length != 1
|
||||
images[ARGV[0]].build(quiet: false)
|
||||
|
||||
when "develop"
|
||||
usage if ARGV.length != 1
|
||||
develop.command(ARGV[0])
|
||||
|
||||
when "vfs"
|
||||
usage if ARGV.length != 1
|
||||
vfs.command(ARGV[0])
|
||||
|
||||
when "integrate"
|
||||
usage if ARGV.length != 1
|
||||
integrate.command(ARGV[0])
|
||||
|
||||
when "run"
|
||||
index = ARGV.index("--")
|
||||
usage if ARGV.length < 3 || index == nil || index == ARGV.length - 1
|
||||
|
||||
image = images[ARGV[0]] || usage
|
||||
image.run(*ARGV[1..-1])
|
||||
|
||||
when "exec"
|
||||
index = ARGV.index("--")
|
||||
usage if ARGV.length < 3 || index == nil || index == ARGV.length - 1
|
||||
|
||||
image = images[ARGV[0]] || usage
|
||||
image.exec(*ARGV[1..-1])
|
||||
|
||||
when "test"
|
||||
force = false
|
||||
while arg = ARGV.shift
|
||||
case arg
|
||||
when "--force" then force = true
|
||||
else usage
|
||||
end
|
||||
end
|
||||
|
||||
tests(images, force: force)
|
||||
|
||||
else
|
||||
usage
|
||||
end
|
||||
|
||||
# vim: set sw=2 et:
|
|
@ -0,0 +1,74 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
def report(name, text)
|
||||
text.split("\n").each do |line|
|
||||
puts "#{name}: #{line}"
|
||||
end
|
||||
end
|
||||
|
||||
def wait_for(name, io, msgs, timeout: 1)
|
||||
buf = String.new
|
||||
start = Time.now
|
||||
|
||||
while !(msg = msgs.find {|m| buf.include?(m)})
|
||||
begin
|
||||
s = io.read_nonblock(1024)
|
||||
rescue IO::WaitReadable
|
||||
remaining = timeout - (Time.now - start)
|
||||
raise "timed out waiting for #{msg.inspect}" if remaining <= 0
|
||||
any = IO.select([io], nil, nil, remaining)
|
||||
retry if any
|
||||
raise "timed out waiting for one of #{msgs.inspect}"
|
||||
rescue EOFError
|
||||
raise "timed out waiting for one of #{msgs.inspect} (got EOF)"
|
||||
end
|
||||
|
||||
report(name, s)
|
||||
buf << s
|
||||
end
|
||||
|
||||
msg
|
||||
end
|
||||
|
||||
MSG_PRESS_ENTER = "Press Enter to end"
|
||||
MSG_CONFLICT = "Conflict. The container name"
|
||||
|
||||
def tests(images, force: false)
|
||||
integration = images["integrate"].command("mount", popen: true)
|
||||
msg = wait_for("integrate", integration, [MSG_PRESS_ENTER, MSG_CONFLICT], timeout: 5)
|
||||
if msg == MSG_CONFLICT
|
||||
puts "integration container already running"
|
||||
system "docker", "ps", "-f", "name=#{images["integrate"].docker_container_name}"
|
||||
if !force
|
||||
raise "cannot run tests; remove container or do so automatically with --force"
|
||||
end
|
||||
|
||||
system "docker", "stop", "-t", "0", images["integrate"].docker_container_name
|
||||
|
||||
integration = images["integrate"].command("mount", popen: true)
|
||||
msg = wait_for("integrate", integration, [MSG_PRESS_ENTER, MSG_CONFLICT], timeout: 5)
|
||||
if msg == MSG_CONFLICT
|
||||
raise "still couldn't start container"
|
||||
end
|
||||
end
|
||||
|
||||
puts "test: checking that touching a file is recognised"
|
||||
|
||||
id = 16.times.map { ("a".."z").to_a.sample(1) }.join
|
||||
images["integrate"].exec("--", "touch", "TestRoot/src/#{id}")
|
||||
msg = wait_for("integrate", integration, ["OnNewFileCreated (isDirectory: False): #{id}"])
|
||||
images["integrate"].exec("--", "rm", "TestRoot/src/#{id}")
|
||||
msg = wait_for("integrate", integration, ["OnPreDelete (isDirectory: False): #{id}"])
|
||||
|
||||
puts "test: finished; stopping mount gracefully"
|
||||
|
||||
integration.write "\n"
|
||||
integration.flush
|
||||
integration.close_write
|
||||
report("integrate", integration.read)
|
||||
integration.close
|
||||
|
||||
puts "test: done"
|
||||
end
|
||||
|
||||
# vim: set sw=2 et:
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require 'commonmarker'
|
||||
|
||||
doc = CommonMarker.render_doc(File.read('README.md'))
|
||||
|
||||
did_replace = false
|
||||
|
||||
doc.walk do |node|
|
||||
if !did_replace && node.type == :code_block && node.string_content.start_with?("$ ./projfs")
|
||||
node.string_content = "$ ./projfs\n" + `./projfs 2>&1`
|
||||
did_replace = true
|
||||
end
|
||||
end
|
||||
|
||||
raise "replaced nothing" unless did_replace
|
||||
|
||||
File.open("README.md", "w") {|f| f.write(doc.to_commonmark)}
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
cat <<EOF
|
||||
noop
|
||||
|
||||
(this exists because we need to have a projfs-linux-private project in Janky in
|
||||
order for projfs-docker to depend on it.)
|
||||
EOF
|
Загрузка…
Ссылка в новой задаче