Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 984752b812 | |||
| 4568429a69 | |||
| 6f40bc91be | |||
| 63d171007e | |||
| 5d4d6410da |
@@ -3,6 +3,7 @@ packages:
|
||||
- go
|
||||
- git
|
||||
- make
|
||||
- shellcheck
|
||||
sources:
|
||||
- https://git.sr.ht/~motiejus/undocker
|
||||
tasks:
|
||||
|
||||
28
Makefile
28
Makefile
@@ -1,44 +1,36 @@
|
||||
SCRIPTS = $(shell awk '/#!\/bin\/(ba)?sh/&&FNR==1{print FILENAME}' $(shell git ls-files))
|
||||
GODEPS = $(shell git ls-files '*.go' go.mod go.sum)
|
||||
GOBIN = $(shell go env GOPATH)/bin/
|
||||
|
||||
GOOSARCHS = $(sort \
|
||||
darwin/amd64 \
|
||||
darwin/arm64 \
|
||||
linux/amd64 \
|
||||
linux/arm64 \
|
||||
windows/amd64/.exe \
|
||||
windows/arm64/.exe)
|
||||
GOOSARCHS = $(sort darwin/amd64 linux/amd64)
|
||||
|
||||
VSN ?= $(shell git describe --dirty)
|
||||
VSNHASH = $(shell git rev-parse --verify HEAD)
|
||||
LDFLAGS = -ldflags "-X main.Version=$(VSN) -X main.VersionHash=$(VSNHASH)"
|
||||
|
||||
undocker: ## builds binary for the current architecture
|
||||
CGO_ENABLED=0 go build $(LDFLAGS) -o $@
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race -cover ./...
|
||||
|
||||
define undockertarget
|
||||
UNDOCKERS += undocker-$(1)-$(2)-$(VSN)$(firstword $(3))
|
||||
undocker-$(1)-$(2)-$(VSN)$(firstword $(3)): $(GODEPS)
|
||||
UNDOCKERS += undocker-$(1)-$(2)-$(VSN)
|
||||
undocker-$(1)-$(2)-$(VSN): $(GODEPS)
|
||||
CGO_ENABLED=0 GOOS=$(1) GOARCH=$(2) go build $(LDFLAGS) -o $$@
|
||||
endef
|
||||
|
||||
$(foreach goosarch,$(GOOSARCHS),\
|
||||
$(eval $(call undockertarget,$(word 1,$(subst /, ,$(goosarch))),$(word 2,$(subst /, ,$(goosarch))),$(word 3,$(subst /, ,$(goosarch))))))
|
||||
$(eval $(call undockertarget,$(word 1,$(subst /, ,$(goosarch))),$(word 2,$(subst /, ,$(goosarch))))))
|
||||
|
||||
.PHONY: all
|
||||
all: $(UNDOCKERS)
|
||||
|
||||
.PHONY: lint
|
||||
lint: vet staticcheck
|
||||
|
||||
.PHONY: vet
|
||||
vet:
|
||||
lint:
|
||||
go vet ./...
|
||||
|
||||
.PHONY: staticcheck
|
||||
staticcheck:
|
||||
$(GOBIN)staticcheck -f stylish ./...
|
||||
shellcheck $(SCRIPTS)
|
||||
|
||||
.INTERMEDIATE: coverage.out
|
||||
coverage.out: $(GODEPS)
|
||||
|
||||
14
README.md
14
README.md
@@ -20,6 +20,19 @@ systemd, FreeBSD Jails, and many others.
|
||||
|
||||
Undocker has no dependencies outside Golang stdlib.
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
We recommend using [officially released binaries][3]. To build the project
|
||||
instead, run:
|
||||
|
||||
```
|
||||
$ make undocker
|
||||
```
|
||||
|
||||
The number of officially released binaries is quite limited. If you'd like me
|
||||
to expand a list, please contribute a patch to the Makefile.
|
||||
|
||||
Usage: convert docker image to rootfs
|
||||
-------------------------------------
|
||||
|
||||
@@ -107,3 +120,4 @@ MIT
|
||||
|
||||
[1]: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
|
||||
[2]: https://fly.io/blog/docker-without-docker/
|
||||
[3]: http://git.sr.ht/~motiejus/undocker
|
||||
|
||||
16
main.go
16
main.go
@@ -53,15 +53,15 @@ type command struct {
|
||||
Stdout io.Writer
|
||||
}
|
||||
|
||||
func (c *command) execute(infile string, outfile string) (err error) {
|
||||
func (c *command) execute(infile string, outfile string) (_err error) {
|
||||
rd, err := os.Open(infile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
err1 := rd.Close()
|
||||
if err == nil {
|
||||
err = err1
|
||||
err := rd.Close()
|
||||
if _err == nil {
|
||||
_err = err
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -74,9 +74,11 @@ func (c *command) execute(infile string, outfile string) (err error) {
|
||||
return fmt.Errorf("create: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
err1 := outf.Close()
|
||||
if err == nil {
|
||||
err = err1
|
||||
err := outf.Close()
|
||||
if _err != nil {
|
||||
os.Remove(outfile)
|
||||
} else {
|
||||
_err = err
|
||||
}
|
||||
}()
|
||||
out = outf
|
||||
|
||||
60
main_test.go
60
main_test.go
@@ -2,8 +2,10 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"testing"
|
||||
@@ -13,11 +15,13 @@ func TestExecute(t *testing.T) {
|
||||
var _foo = []byte("foo foo")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
fixture func(*testing.T, string)
|
||||
infile string
|
||||
outfile string
|
||||
wantErr string
|
||||
name string
|
||||
fixture func(*testing.T, string)
|
||||
flattener func(io.ReadSeeker, io.Writer) error
|
||||
infile string
|
||||
outfile string
|
||||
wantErr string
|
||||
assertion func(*testing.T, string)
|
||||
}{
|
||||
{
|
||||
name: "ok passthrough via stdout",
|
||||
@@ -41,6 +45,31 @@ func TestExecute(t *testing.T) {
|
||||
},
|
||||
outfile: "t20-out.txt",
|
||||
},
|
||||
{
|
||||
name: "bad flattener should remove the file",
|
||||
infile: "t30-in.txt",
|
||||
fixture: func(t *testing.T, dir string) {
|
||||
fname := filepath.Join(dir, "t30-in.txt")
|
||||
if err := ioutil.WriteFile(fname, _foo, 0644); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
},
|
||||
flattener: flattenBad,
|
||||
outfile: "t30-out.txt",
|
||||
wantErr: "some error",
|
||||
assertion: func(t *testing.T, dir string) {
|
||||
d, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if len(d) != 1 {
|
||||
t.Fatalf("expected 1 entry, got %d", len(d))
|
||||
}
|
||||
if d[0].Name() != "t30-in.txt" {
|
||||
t.Fatalf("expected to find only t30-in.txt, got %s", d[0].Name())
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "infile does not exist",
|
||||
infile: "t3-does-not-exist.txt",
|
||||
@@ -57,7 +86,10 @@ func TestExecute(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
var stdout bytes.Buffer
|
||||
c := &command{Stdout: &stdout}
|
||||
if tt.flattener == nil {
|
||||
tt.flattener = flattenPassthrough
|
||||
}
|
||||
|
||||
if tt.fixture != nil {
|
||||
tt.fixture(t, dir)
|
||||
}
|
||||
@@ -65,9 +97,14 @@ func TestExecute(t *testing.T) {
|
||||
tt.outfile = filepath.Join(dir, tt.outfile)
|
||||
}
|
||||
inf := filepath.Join(dir, tt.infile)
|
||||
c.flattener = flattenPassthrough
|
||||
|
||||
c := &command{Stdout: &stdout, flattener: tt.flattener}
|
||||
err := c.execute(inf, tt.outfile)
|
||||
|
||||
if tt.assertion != nil {
|
||||
tt.assertion(t, dir)
|
||||
}
|
||||
|
||||
if tt.wantErr != "" {
|
||||
if err == nil {
|
||||
t.Fatal("expected error, got nil")
|
||||
@@ -78,10 +115,10 @@ func TestExecute(t *testing.T) {
|
||||
}
|
||||
return
|
||||
}
|
||||
var out []byte
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
var out []byte
|
||||
if tt.outfile == "-" {
|
||||
out = stdout.Bytes()
|
||||
} else {
|
||||
@@ -91,8 +128,9 @@ func TestExecute(t *testing.T) {
|
||||
}
|
||||
}
|
||||
if !bytes.Equal([]byte("foo foo"), out) {
|
||||
t.Errorf("out != foo foo: %s", string(out))
|
||||
t.Errorf("out != foo foo: %q", string(out))
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -101,3 +139,7 @@ func flattenPassthrough(r io.ReadSeeker, w io.Writer) error {
|
||||
_, err := io.Copy(w, r)
|
||||
return err
|
||||
}
|
||||
|
||||
func flattenBad(_ io.ReadSeeker, _ io.Writer) error {
|
||||
return errors.New("some error")
|
||||
}
|
||||
|
||||
12
release
12
release
@@ -6,24 +6,24 @@ err() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
[[ -n "$(git status --porcelain)" ]] && \
|
||||
git status --porcelain | grep -q "" &&
|
||||
err "working tree is dirty, commit your changes first."
|
||||
|
||||
[[ ! "$1" =~ ^v([0-9]+)\.([0-9]+)(\.([0-9]+))?$ ]] && \
|
||||
err "arg1 accepts the following formats: v1.0 v1.0.0"
|
||||
|
||||
[[ -n "$(git tag | grep "^$1$")" ]] && \
|
||||
git tag | grep -q "^$1$" &&
|
||||
err "tag $1 already exists"
|
||||
|
||||
last_tag=$(git tag | tail -1)
|
||||
|
||||
make -B -j$(nproc) VSN=$1 sha256sum.txt.asc
|
||||
make -B -j"$(nproc)" VSN="$1" sha256sum.txt.asc
|
||||
|
||||
{
|
||||
echo undocker $1
|
||||
echo undocker "$1"
|
||||
echo
|
||||
echo Changelog since $last_tag:
|
||||
git log --pretty=format:"- [%cn] %s" $last_tag..HEAD
|
||||
echo Changelog since "$last_tag":
|
||||
git log --pretty=format:"- [%cn] %s" "$last_tag"..HEAD
|
||||
echo
|
||||
echo
|
||||
echo sha256sums of released binaries:
|
||||
|
||||
Reference in New Issue
Block a user