feat(cli): add BuildSourceArchive for plugin publish tar.zst
This commit is contained in:
parent
680cbe0160
commit
31e7b72b49
41
cmd/ninja/internal/archive/archive.go
Normal file
41
cmd/ninja/internal/archive/archive.go
Normal file
@ -0,0 +1,41 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
|
||||
"github.com/klauspost/compress/zstd"
|
||||
)
|
||||
|
||||
// BuildSourceArchive runs `git archive --format=tar HEAD` in repoDir and
|
||||
// compresses the result with zstd. Returns the compressed bytes.
|
||||
//
|
||||
// Only tracked files at HEAD are included. .gitignored files that were
|
||||
// never tracked are excluded. Tracked-then-gitignored files are still
|
||||
// included — callers may warn separately.
|
||||
func BuildSourceArchive(repoDir string) ([]byte, error) {
|
||||
cmd := exec.Command("git", "archive", "--format=tar", "HEAD")
|
||||
cmd.Dir = repoDir
|
||||
var tarOut, stderr bytes.Buffer
|
||||
cmd.Stdout = &tarOut
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
return nil, fmt.Errorf("git archive: %v: %s", err, stderr.String())
|
||||
}
|
||||
|
||||
var compressed bytes.Buffer
|
||||
enc, err := zstd.NewWriter(&compressed, zstd.WithEncoderLevel(zstd.SpeedDefault))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := io.Copy(enc, &tarOut); err != nil {
|
||||
_ = enc.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err := enc.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return compressed.Bytes(), nil
|
||||
}
|
||||
89
cmd/ninja/internal/archive/archive_test.go
Normal file
89
cmd/ninja/internal/archive/archive_test.go
Normal file
@ -0,0 +1,89 @@
|
||||
package archive
|
||||
|
||||
import (
|
||||
"archive/tar"
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/klauspost/compress/zstd"
|
||||
)
|
||||
|
||||
func TestBuildSourceArchive_RoundTrip(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
run := func(name string, args ...string) {
|
||||
t.Helper()
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.Dir = dir
|
||||
cmd.Env = append(os.Environ(),
|
||||
"GIT_AUTHOR_NAME=t",
|
||||
"GIT_AUTHOR_EMAIL=t@t",
|
||||
"GIT_COMMITTER_NAME=t",
|
||||
"GIT_COMMITTER_EMAIL=t@t",
|
||||
)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("%s %v: %v\n%s", name, args, err, out)
|
||||
}
|
||||
}
|
||||
run("git", "init", "-q")
|
||||
if err := os.WriteFile(filepath.Join(dir, "plugin.mod"),
|
||||
[]byte("[plugin]\nname=\"x\"\nscope=\"@s\"\nversion=\"0.1.0\"\n"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "ignored.log"), []byte("nope"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, ".gitignore"), []byte("ignored.log\n"), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
run("git", "add", "plugin.mod", ".gitignore")
|
||||
run("git", "commit", "-qm", "init")
|
||||
|
||||
zstdBytes, err := BuildSourceArchive(dir)
|
||||
if err != nil {
|
||||
t.Fatalf("BuildSourceArchive: %v", err)
|
||||
}
|
||||
if len(zstdBytes) == 0 {
|
||||
t.Fatal("empty archive")
|
||||
}
|
||||
|
||||
dec, err := zstd.NewReader(bytes.NewReader(zstdBytes))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer dec.Close()
|
||||
tr := tar.NewReader(dec)
|
||||
got := map[string]string{}
|
||||
for {
|
||||
hdr, err := tr.Next()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
buf, err := io.ReadAll(tr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got[hdr.Name] = string(buf)
|
||||
}
|
||||
if _, ok := got["plugin.mod"]; !ok {
|
||||
t.Errorf("expected plugin.mod in archive, got %v", keys(got))
|
||||
}
|
||||
if _, ok := got["ignored.log"]; ok {
|
||||
t.Errorf("ignored.log should not be in archive (gitignored + untracked)")
|
||||
}
|
||||
}
|
||||
|
||||
func keys(m map[string]string) []string {
|
||||
out := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
out = append(out, k)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user