Compare commits

..

No commits in common. "99e89d60d4e7ff56427b1d05601b0edc4fdcf769" and "295919fbc9de218bd6e9c5c68ce4bb2dcf1f894b" have entirely different histories.

13 changed files with 128 additions and 174 deletions

View File

@ -1,2 +0,0 @@
run:
tests: false

View File

@ -4,24 +4,20 @@ export PATH := $(PATH):$(GOPATH)/bin
PROTOC_GEN_GO := $(GOPATH)/bin/protoc-gen-go
ARCH := $(shell uname -m)
GITREV := $(shell git describe --always --dirty=-dirty)
VERSION := $(shell git describe --always --dirty=-dirty)
GOLDFLAGS += -X main.Version=0.1.0
GOLDFLAGS += -X main.Gitrev=$(GITREV)
GOLDFLAGS += -X main.Version=$(VERSION)
GOFLAGS := -ldflags "$(GOLDFLAGS)"
default: run
run: ./mfer.cmd
./$<
./$< gen --ignore-dotfiles
./$< gen
$(PROTOC_GEN_GO):
test -e $(PROTOC_GEN_GO) || go install -v google.golang.org/protobuf/cmd/protoc-gen-go@latest
fixme:
@grep -nir fixme . | grep -v Makefile
devprereqs:
which gofumpt || go install -v mvdan.cc/gofumpt@latest
which golangci-lint || go install -v github.com/golangci/golangci-lint/cmd/golangci-lint@latest
@ -29,16 +25,15 @@ devprereqs:
mfer.cmd: $(PROTOC_GEN_GO) mfer/*.go internal/*/*.go cmd/*/*.go
protoc --version
cd mfer && go generate .
cd cmd/mfer && go build -tags urfave_cli_no_docs -o ../../mfer.cmd $(GOFLAGS) .
cd cmd/mfer && go build -o ../../mfer.cmd $(GOFLAGS) .
clean:
rm -rfv mfer/*.pb.go mfer.cmd cmd/mfer/mfer
rm -rfv mfer/*.pb.go ./mfer
fmt: devprereqs
fmt: prereqs
gofumpt -l -w mfer internal cmd
golangci-lint run --fix
-prettier -w *.json
-prettier -w *.md
prettier -w *.json *.md
lint:
golangci-lint run

View File

@ -128,7 +128,8 @@ The manifest file would do several important things:
- a command line option to zero/omit mtime/ctime, as well as manifest
timestamp, and sort all directory listings so that manifest file
generation is deterministic/reproducible
- URL format `mfer fetch https://exmaple.com/manifestdirectory/?key=5539AD00DE4C42F3AFE11575052443F4DF2A55C2`
- URL format `mfer fetch
https://exmaple.com/manifestdirectory/?key=5539AD00DE4C42F3AFE11575052443F4DF2A55C2`
to assert in the URL which PGP signing key should be used in the manifest,
so that shared URLs have a cryptographic trust root
- a "well-known" key in the manifest that maps well known keys (could reuse

View File

@ -9,9 +9,8 @@ import (
var (
Appname string = "mfer"
Version string
Gitrev string
)
func main() {
os.Exit(cli.Run(Appname, Version, Gitrev))
os.Exit(cli.Run(Appname, Version))
}

View File

@ -1,14 +0,0 @@
package cli
import (
"errors"
log "github.com/visionmedia/go-cli-log"
"github.com/urfave/cli/v2"
)
func (mfa *CLIApp) checkManifestOperation(c *cli.Context) error {
log.Error(errors.New("unimplemented"))
return nil
}

View File

@ -13,11 +13,10 @@ func init() {
}
}
func Run(Appname, Version, Gitrev string) int {
func Run(Appname, Version string) int {
m := &CLIApp{}
m.appname = Appname
m.version = Version
m.gitrev = Gitrev
m.exitCode = 0
m.run()

View File

@ -1,12 +0,0 @@
package cli
import (
"fmt"
"github.com/urfave/cli/v2"
)
func (mfa *CLIApp) fetchManifestOperation(c *cli.Context) error {
fmt.Println("fetchManifestOperation()")
return nil
}

View File

@ -1,36 +0,0 @@
package cli
import (
"fmt"
"git.eeqj.de/sneak/mfer/mfer"
"github.com/davecgh/go-spew/spew"
"github.com/urfave/cli/v2"
)
func (mfa *CLIApp) generateManifestOperation(c *cli.Context) error {
fmt.Println("generateManifestOperation()")
myArgs := c.Args()
spew.Dump(myArgs)
fmt.Printf("%#v\n", c.Args().First())
if c.Args().Len() > 0 {
fmt.Printf("%#v\n", c.Args().Get(1))
}
//fmt.Printf("called with arg: %s\n", c.String("input"))
opts := &mfer.ManifestScanOptions{
IgnoreDotfiles: c.Bool("IgnoreDotfiles"),
FollowSymLinks: c.Bool("FollowSymLinks"),
}
// FIXME add command flags for ignoring dotfiles and following symlinks
mf, err := mfer.NewFromPath(c.String("input"), opts)
if err != nil {
panic(err)
}
spew.Dump(mf)
return nil
}

51
internal/cli/manifest.go Normal file
View File

@ -0,0 +1,51 @@
package cli
import (
"git.eeqj.de/sneak/mfer/mfer"
"github.com/spf13/afero"
)
type Job struct {
innerpb *mfer.MFFileInner
outerpb *mfer.MFFile
fileCount int64
totalSize int64
afs afero.Fs
}
func (m *Job) scanForFiles() error {
m.innerpb = &mfer.MFFileInner{}
m.innerpb.Version = mfer.MFFileInner_ONE
return nil
}
/*
walkErr := filepath.Walk(m.sourcePath, func(itemPath string, info os.FileInfo, err error) error {
// we do not include the manifest file in the manifest
if itemPath == "index.mf" {
return nil
}
fpi := mfer.MFFilePath{}
fpi.Path = itemPath
fpi.Size = info.Size()
m.innerpb.Files = append(m.innerpb.Files, &fpi)
m.fileCount++
m.totalSize += fpi.Size
return nil
})
if walkErr != nil {
log.Fatal(walkErr)
return walkErr
}
fmt.Printf("%#v\n", m.innerpb)
fmt.Printf("filecount = %#v\n", m.fileCount)
fmt.Printf("totalsize = %#v\n", m.totalSize)
return nil
}
*/

View File

@ -1,12 +1,15 @@
package cli
import (
"errors"
"fmt"
"os"
"time"
log "github.com/visionmedia/go-cli-log"
"git.eeqj.de/sneak/mfer/mfer"
"github.com/davecgh/go-spew/spew"
"github.com/pterm/pterm"
"github.com/urfave/cli/v2"
)
@ -14,9 +17,10 @@ import (
type CLIApp struct {
appname string
version string
gitrev string
buildarch string
startupTime time.Time
exitCode int
errorString string
app *cli.App
}
@ -36,58 +40,29 @@ func (mfa *CLIApp) disableStyling() {
pterm.Fatal.Prefix.Text = ""
}
func (mfa *CLIApp) VersionString() string {
return fmt.Sprintf("%s (%s)", mfa.version, mfa.gitrev)
}
func (mfa *CLIApp) run() {
mfa.startupTime = time.Now()
if NO_COLOR {
// shoutout to rob pike who thinks it's juvenile
mfa.disableStyling()
}
mfa.printBanner()
mfa.app = &cli.App{
Name: mfa.appname,
Usage: "Manifest generator",
Version: mfa.VersionString(),
Version: mfa.version,
EnableBashCompletion: true,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "verbose",
Usage: "Verbosity level",
Aliases: []string{"v"},
},
&cli.BoolFlag{
Name: "quiet",
Usage: "don't produce output except on error",
Aliases: []string{"q"},
},
},
Commands: []*cli.Command{
{
Name: "generate",
Aliases: []string{"gen"},
Usage: "Generate manifest file",
Action: func(c *cli.Context) error {
if !c.Bool("quiet") {
mfa.printBanner()
}
return mfa.generateManifestOperation(c)
},
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "FollowSymLinks",
Aliases: []string{"follow-symlinks"},
Usage: "Resolve encountered symlinks",
},
&cli.BoolFlag{
Name: "IgnoreDotfiles",
Aliases: []string{"ignore-dotfiles"},
Usage: "Ignore any dot (hidden) files encountered",
},
// FIXME this should be a positional arg
&cli.StringFlag{
Name: "input",
Value: ".",
@ -106,37 +81,51 @@ func (mfa *CLIApp) run() {
Name: "check",
Usage: "Validate files using manifest file",
Action: func(c *cli.Context) error {
if !c.Bool("quiet") {
mfa.printBanner()
}
return mfa.checkManifestOperation(c)
},
},
{
Name: "version",
Usage: "Show version",
Action: func(c *cli.Context) error {
fmt.Printf("%s\n", mfa.VersionString())
return nil
},
},
{
Name: "fetch",
Usage: "fetch manifest and referenced files",
Action: func(c *cli.Context) error {
if !c.Bool("quiet") {
mfa.printBanner()
}
return mfa.fetchManifestOperation(c)
return mfa.validateManifestOperation(c)
},
},
},
}
mfa.app.HideVersion = true
err := mfa.app.Run(os.Args)
if err != nil {
mfa.exitCode = 1
log.Error(err)
}
}
func (mfa *CLIApp) validateManifestOperation(c *cli.Context) error {
log.Error(errors.New("unimplemented"))
return nil
}
func (mfa *CLIApp) generateManifestOperation(c *cli.Context) error {
fmt.Println("generateManifestOperation()")
fmt.Printf("called with arg: %s\n", c.String("input"))
opts := &mfer.ManifestScanOptions{
IgnoreDotfiles: true,
FollowSymLinks: false,
}
mf, err := mfer.NewFromPath(c.String("input"), opts)
if err != nil {
panic(err)
}
spew.Dump(mf)
/*
mgj, err := NewMFGenerationJobFromFilesystem(c.String("input"))
if err != nil {
log.Fatal(err)
return err
}
mgj.scanForFiles()
//mgj.outputFile = c.String("output")
*/
return nil
}

View File

@ -4,10 +4,10 @@ import (
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
"github.com/davecgh/go-spew/spew"
"github.com/spf13/afero"
)
@ -28,10 +28,6 @@ type Manifest struct {
TotalFileSize int64
}
func (m *Manifest) String() string {
return fmt.Sprintf("<Manifest count=%d totalSize=%d>", len(m.Files), m.TotalFileSize)
}
type ManifestScanOptions struct {
IgnoreDotfiles bool
FollowSymLinks bool
@ -43,11 +39,13 @@ func NewFromPath(inputPath string, options *ManifestScanOptions) (*Manifest, err
return nil, err
}
afs := afero.NewBasePathFs(afero.NewOsFs(), abs)
spew.Dump(afs)
m, err := NewFromFS(afs, options)
if err != nil {
return nil, err
}
m.SourceFSRoot = abs
spew.Dump(m)
return m, nil
}
@ -56,16 +54,13 @@ func NewFromFS(fs afero.Fs, options *ManifestScanOptions) (*Manifest, error) {
SourceFS: fs,
ScanOptions: options,
}
err := m.Scan()
if err != nil {
return nil, err
}
m.Scan()
return m, nil
}
func (m *Manifest) Scan() error {
// FIXME scan and whatever function does the hashing should take ctx
oe := afero.Walk(m.SourceFS, "./", func(path string, info fs.FileInfo, err error) error {
func (m *Manifest) Scan() {
afero.Walk(m.SourceFS, "./", func(path string, info fs.FileInfo, err error) error {
if m.ScanOptions.IgnoreDotfiles && strings.HasPrefix(path, ".") {
// FIXME make this check all path components BUG
return nil
@ -76,6 +71,10 @@ func (m *Manifest) Scan() error {
return nil
}
fmt.Printf("path = %s\n", path)
spew.Dump(path)
spew.Dump(info)
fileinfo, staterr := m.SourceFS.Stat(path)
if staterr != nil {
panic(staterr)
@ -87,28 +86,12 @@ func (m *Manifest) Scan() error {
}
m.Files = append(m.Files, nf)
m.TotalFileSize = m.TotalFileSize + info.Size()
fmt.Printf("total file count now %i\n", len(m.Files))
fmt.Printf("total file size now %i\n", m.TotalFileSize)
return nil
})
if oe != nil {
return oe
}
return nil
}
func (m *Manifest) WriteToFile(path string) error {
// FIXME refuse to overwrite without -f if file exists
f, err := os.Create(path)
if err != nil {
return err
}
defer f.Close()
return m.Write(f)
}
func (m *Manifest) Write(output io.Writer) error {
// FIXME implement
panic("nope")
return nil // nolint:all
return nil
}

View File

@ -14,12 +14,12 @@ message MFFile {
}
// required mffile root attributes 1xx
Version version = 101;
bytes innerMessage = 102;
Version version = 1;
bytes innerMessage = 2;
// these are used solely to detect corruption/truncation
// and not for cryptographic integrity.
int64 size = 103;
bytes sha256 = 104;
int64 size = 3;
bytes sha256 = 4;
// 2xx for optional manifest root attributes
// think we might use gosignify instead of gpg:
@ -59,10 +59,10 @@ message MFFileInner {
NONE = 0;
ONE = 1; // only one for now
}
Version version = 100;
Version version = 1;
// required manifest attributes:
repeated MFFilePath files = 101;
repeated MFFilePath files = 2;
// optional manifest attributes 2xx:
optional Timestamp createdAt = 201;

View File

@ -9,4 +9,5 @@ var (
)
func TestManifestGeneration(t *testing.T) {
}