From c88b5216171f3937cd62b67ceb4004f389f180d7 Mon Sep 17 00:00:00 2001 From: Petar Maymounkov Date: Tue, 31 Oct 2023 22:48:32 -0700 Subject: [PATCH] fix use of git path vs os path (#24) * NS.Path->NS.OSPath; ns.ParseFromOSPath+ns.ParseFromGitPath; pkg file uses git paths to talk to billy filesystem * remove stale id package * all path arguments for git file system manipulation are now ns.NS * add ns.Append * update github.com/go-git/go-git and go.uber.org/zap dependencies * add ns.Dir and ns.Base; use NS paths in ListFilesRecursively * add TreeRemove and TreeReadDir --- file/file.go | 8 +++---- form/form.go | 19 ++++++++-------- git/fs.go | 15 ++++++++----- git/git.go | 4 ++-- git/tree.go | 60 +++++++++++++++++++++++++++++++------------------ go.mod | 14 +++++------- go.sum | 47 +++++++++++++++++--------------------- id/crypto.go | 52 ------------------------------------------ id/id.go | 34 ---------------------------- id/init.go | 58 ----------------------------------------------- id/init_test.go | 18 --------------- id/private.go | 20 ----------------- id/public.go | 16 ------------- id/schema.go | 32 -------------------------- id/test_id.go | 42 ---------------------------------- ns/ns.go | 44 +++++++++++++++++++++++++++--------- 16 files changed, 123 insertions(+), 360 deletions(-) delete mode 100644 id/crypto.go delete mode 100644 id/id.go delete mode 100644 id/init.go delete mode 100644 id/init_test.go delete mode 100644 id/private.go delete mode 100644 id/public.go delete mode 100644 id/schema.go delete mode 100644 id/test_id.go diff --git a/file/file.go b/file/file.go index 3bc9ae2..12c859f 100644 --- a/file/file.go +++ b/file/file.go @@ -2,7 +2,7 @@ package file import ( "context" - "io/ioutil" + "io" "os" "github.com/go-git/go-billy/v5" @@ -19,7 +19,7 @@ func FileToString(ctx context.Context, fs billy.Filesystem, path ns.NS) string { } func BytesToFile(ctx context.Context, fs billy.Filesystem, path ns.NS, content []byte) { - file, err := fs.OpenFile(path.Path(), os.O_CREATE|os.O_RDWR, 0644) + file, err := fs.OpenFile(path.GitPath(), os.O_CREATE|os.O_RDWR, 0644) must.NoError(ctx, err) defer file.Close() _, err = file.Write(content) @@ -27,9 +27,9 @@ func BytesToFile(ctx context.Context, fs billy.Filesystem, path ns.NS, content [ } func FileToBytes(ctx context.Context, fs billy.Filesystem, path ns.NS) []byte { - file, err := fs.Open(path.Path()) + file, err := fs.Open(path.GitPath()) must.NoError(ctx, err) - content, err := ioutil.ReadAll(file) + content, err := io.ReadAll(file) must.NoError(ctx, err) return content } diff --git a/form/form.go b/form/form.go index 8f7d4dd..ba66aca 100644 --- a/form/form.go +++ b/form/form.go @@ -7,6 +7,7 @@ import ( "github.com/go-git/go-billy/v5" "github.com/gov4git/lib4git/must" + "github.com/gov4git/lib4git/ns" ) type Form interface{} @@ -59,8 +60,8 @@ func DecodeBytesInto(ctx context.Context, data []byte, into Form) error { return json.Unmarshal(data, into) } -func EncodeToFile[F Form](ctx context.Context, fs billy.Filesystem, path string, form F) error { - file, err := fs.Create(path) +func EncodeToFile[F Form](ctx context.Context, fs billy.Filesystem, path ns.NS, form F) error { + file, err := fs.Create(path.GitPath()) if err != nil { return err } @@ -68,8 +69,8 @@ func EncodeToFile[F Form](ctx context.Context, fs billy.Filesystem, path string, return Encode(ctx, file, form) } -func DecodeFromFile[F Form](ctx context.Context, fs billy.Filesystem, path string) (form F, err error) { - file, err := fs.Open(path) +func DecodeFromFile[F Form](ctx context.Context, fs billy.Filesystem, path ns.NS) (form F, err error) { + file, err := fs.Open(path.GitPath()) if err != nil { return form, err } @@ -77,8 +78,8 @@ func DecodeFromFile[F Form](ctx context.Context, fs billy.Filesystem, path strin return Decode[F](ctx, file) } -func DecodeFromFileInto(ctx context.Context, fs billy.Filesystem, path string, into Form) error { - file, err := fs.Open(path) +func DecodeFromFileInto(ctx context.Context, fs billy.Filesystem, path ns.NS, into Form) error { + file, err := fs.Open(path.GitPath()) if err != nil { return err } @@ -86,13 +87,13 @@ func DecodeFromFileInto(ctx context.Context, fs billy.Filesystem, path string, i return DecodeInto(ctx, file, into) } -func ToFile[F Form](ctx context.Context, fs billy.Filesystem, path string, form F) { +func ToFile[F Form](ctx context.Context, fs billy.Filesystem, path ns.NS, form F) { if err := EncodeToFile(ctx, fs, path, form); err != nil { must.Panic(ctx, err) } } -func FromFile[F Form](ctx context.Context, fs billy.Filesystem, path string) F { +func FromFile[F Form](ctx context.Context, fs billy.Filesystem, path ns.NS) F { f, err := DecodeFromFile[F](ctx, fs, path) if err != nil { must.Panic(ctx, err) @@ -100,6 +101,6 @@ func FromFile[F Form](ctx context.Context, fs billy.Filesystem, path string) F { return f } -func FromFileInto(ctx context.Context, fs billy.Filesystem, path string, into Form) { +func FromFileInto(ctx context.Context, fs billy.Filesystem, path ns.NS, into Form) { must.NoError(ctx, DecodeFromFileInto(ctx, fs, path, into)) } diff --git a/git/fs.go b/git/fs.go index 522dbc3..46d80cc 100644 --- a/git/fs.go +++ b/git/fs.go @@ -1,23 +1,26 @@ package git -import "path/filepath" +import ( + "github.com/gov4git/lib4git/ns" +) -func ListFilesRecursively(t *Tree, dir string) ([]string, error) { +func ListFilesRecursively(t *Tree, dir ns.NS) ([]ns.NS, error) { fs := t.Filesystem - infos, err := fs.ReadDir(dir) + infos, err := fs.ReadDir(dir.GitPath()) if err != nil { return nil, err } - list := []string{} + list := []ns.NS{} for _, info := range infos { + childPath := dir.Append(info.Name()) if info.IsDir() { - sublist, err := ListFilesRecursively(t, filepath.Join(dir, info.Name())) + sublist, err := ListFilesRecursively(t, childPath) if err != nil { return nil, err } list = append(list, sublist...) } else { - list = append(list, filepath.Join(dir, info.Name())) + list = append(list, childPath) } } return list, nil diff --git a/git/git.go b/git/git.go index 0f256c1..10a4212 100644 --- a/git/git.go +++ b/git/git.go @@ -110,8 +110,8 @@ func Worktree(ctx context.Context, repo *Repository) *Tree { return wt } -func Add(ctx context.Context, wt *Tree, path string) { - if _, err := wt.Add(path); err != nil { +func Add(ctx context.Context, wt *Tree, path ns.NS) { + if _, err := wt.Add(path.GitPath()); err != nil { must.Panic(ctx, err) } } diff --git a/git/tree.go b/git/tree.go index 1583014..4cabb98 100644 --- a/git/tree.go +++ b/git/tree.go @@ -2,8 +2,9 @@ package git import ( "context" - "path/filepath" + "io/fs" + "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/format/index" "github.com/gov4git/lib4git/file" "github.com/gov4git/lib4git/form" @@ -11,21 +12,36 @@ import ( "github.com/gov4git/lib4git/ns" ) -func TreeMkdirAll(ctx context.Context, t *Tree, path string) { - err := t.Filesystem.MkdirAll(path, 0755) +func TreeMkdirAll(ctx context.Context, t *Tree, path ns.NS) { + if path.Len() == 0 { + return + } + err := t.Filesystem.MkdirAll(path.GitPath(), 0755) must.NoError(ctx, err) } +func TreeStat(ctx context.Context, t *Tree, path ns.NS) (fs.FileInfo, error) { + return t.Filesystem.Stat(path.GitPath()) +} + +func TreeRemove(ctx context.Context, t *Tree, path ns.NS) (plumbing.Hash, error) { + return t.Remove(path.GitPath()) +} + +func TreeReadDir(ctx context.Context, t *Tree, path ns.NS) ([]fs.FileInfo, error) { + return t.Filesystem.ReadDir(path.GitPath()) +} + // func BytesToFile(ctx context.Context, t *Tree, path ns.NS, content []byte) { - TreeMkdirAll(ctx, t, filepath.Dir(path.Path())) + TreeMkdirAll(ctx, t, path.Dir()) file.BytesToFile(ctx, t.Filesystem, path, content) } func BytesToFileStage(ctx context.Context, t *Tree, path ns.NS, content []byte) { BytesToFile(ctx, t, path, content) - Add(ctx, t, path.Path()) + Add(ctx, t, path) } func FileToBytes(ctx context.Context, t *Tree, path ns.NS) []byte { @@ -35,13 +51,13 @@ func FileToBytes(ctx context.Context, t *Tree, path ns.NS) []byte { // func StringToFile(ctx context.Context, t *Tree, path ns.NS, content string) { - TreeMkdirAll(ctx, t, filepath.Dir(path.Path())) + TreeMkdirAll(ctx, t, path.Dir()) file.StringToFile(ctx, t.Filesystem, path, content) } func StringToFileStage(ctx context.Context, t *Tree, path ns.NS, content string) { StringToFile(ctx, t, path, content) - Add(ctx, t, path.Path()) + Add(ctx, t, path) } func FileToString(ctx context.Context, t *Tree, path ns.NS) string { @@ -50,25 +66,25 @@ func FileToString(ctx context.Context, t *Tree, path ns.NS) string { // -func ToFile[V form.Form](ctx context.Context, t *Tree, filePath string, value V) { - TreeMkdirAll(ctx, t, filepath.Dir(filePath)) +func ToFile[V form.Form](ctx context.Context, t *Tree, filePath ns.NS, value V) { + TreeMkdirAll(ctx, t, filePath.Dir()) form.ToFile(ctx, t.Filesystem, filePath, value) } -func ToFileStage[V form.Form](ctx context.Context, t *Tree, filePath string, value V) { +func ToFileStage[V form.Form](ctx context.Context, t *Tree, filePath ns.NS, value V) { ToFile(ctx, t, filePath, value) Add(ctx, t, filePath) } -func FromFile[V form.Form](ctx context.Context, t *Tree, filePath string) V { +func FromFile[V form.Form](ctx context.Context, t *Tree, filePath ns.NS) V { return form.FromFile[V](ctx, t.Filesystem, filePath) } -func FromFileInto(ctx context.Context, t *Tree, filePath string, into form.Form) { +func FromFileInto(ctx context.Context, t *Tree, filePath ns.NS, into form.Form) { form.FromFileInto(ctx, t.Filesystem, filePath, into) } -func TryFromFile[V form.Form](ctx context.Context, t *Tree, filePath string) (v V, err error) { +func TryFromFile[V form.Form](ctx context.Context, t *Tree, filePath ns.NS) (v V, err error) { err = must.Try( func() { v = FromFile[V](ctx, t, filePath) @@ -77,8 +93,8 @@ func TryFromFile[V form.Form](ctx context.Context, t *Tree, filePath string) (v return } -func RenameStage(ctx context.Context, t *Tree, oldPath, newPath string) { - stat, err := t.Filesystem.Stat(oldPath) +func RenameStage(ctx context.Context, t *Tree, oldPath, newPath ns.NS) { + stat, err := t.Filesystem.Stat(oldPath.GitPath()) must.NoError(ctx, err) if stat.IsDir() { renameStageDir(ctx, t, oldPath, newPath) @@ -87,20 +103,20 @@ func RenameStage(ctx context.Context, t *Tree, oldPath, newPath string) { } } -func renameStageDir(ctx context.Context, t *Tree, oldPath, newPath string) { - infos, err := t.Filesystem.ReadDir(oldPath) +func renameStageDir(ctx context.Context, t *Tree, oldPath, newPath ns.NS) { + infos, err := t.Filesystem.ReadDir(oldPath.GitPath()) must.NoError(ctx, err) for _, info := range infos { - RenameStage(ctx, t, filepath.Join(oldPath, info.Name()), filepath.Join(newPath, info.Name())) + RenameStage(ctx, t, oldPath.Sub(info.Name()), newPath.Sub(info.Name())) } } -func renameStageFile(ctx context.Context, t *Tree, oldPath, newPath string) { - must.NoError(ctx, t.Filesystem.Rename(oldPath, newPath)) - _, err := t.Remove(oldPath) +func renameStageFile(ctx context.Context, t *Tree, oldPath, newPath ns.NS) { + must.NoError(ctx, t.Filesystem.Rename(oldPath.GitPath(), newPath.GitPath())) + _, err := t.Remove(oldPath.GitPath()) if err != index.ErrEntryNotFound { must.NoError(ctx, err) } - _, err = t.Add(newPath) + _, err = t.Add(newPath.GitPath()) must.NoError(ctx, err) } diff --git a/go.mod b/go.mod index df752b1..92164f1 100644 --- a/go.mod +++ b/go.mod @@ -4,11 +4,10 @@ go 1.21 require ( github.com/go-git/go-billy/v5 v5.5.0 - github.com/go-git/go-git/v5 v5.9.0 + github.com/go-git/go-git/v5 v5.10.0 github.com/gofrs/flock v0.8.1 - github.com/google/uuid v1.3.0 github.com/whilp/git-urls v1.0.0 - go.uber.org/zap v1.24.0 + go.uber.org/zap v1.26.0 ) require ( @@ -27,12 +26,11 @@ require ( github.com/sergi/go-diff v1.1.0 // indirect github.com/skeema/knownhosts v1.2.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.6.0 // indirect - golang.org/x/crypto v0.13.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/crypto v0.14.0 // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.13.0 // indirect golang.org/x/tools v0.13.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index 85812d2..64a5db4 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,6 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= @@ -31,18 +29,16 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66D github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= -github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY= -github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.10.0 h1:F0x3xXrAWmhwtzoCokU4IMPcBdncG+HAAqi9FcOOjbQ= +github.com/go-git/go-git/v5 v5.10.0/go.mod h1:1FOZ/pQnqw24ghP2n7cunVl0ON55BsjPYvhWHvZGhoo= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= @@ -73,30 +69,27 @@ github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJC github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/whilp/git-urls v1.0.0 h1:95f6UMWN5FKW71ECsXRUd3FVYiXdrE7aX4NZKcPmIjU= github.com/whilp/git-urls v1.0.0/go.mod h1:J16SAmobsqc3Qcy98brfl5f5+e0clUvg1krgwk/qCfE= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= @@ -108,8 +101,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -128,15 +121,15 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/id/crypto.go b/id/crypto.go deleted file mode 100644 index 373a7f1..0000000 --- a/id/crypto.go +++ /dev/null @@ -1,52 +0,0 @@ -package id - -import ( - "context" - "crypto/ed25519" - - "github.com/gov4git/lib4git/form" - "github.com/gov4git/lib4git/must" -) - -type Ed25519PublicKey = form.Bytes - -type Ed25519PrivateKey = form.Bytes - -func GenerateCredentials() (PrivateCredentials, error) { - pubKey, privKey, err := ed25519.GenerateKey(nil) - if err != nil { - return PrivateCredentials{}, err - } - return PrivateCredentials{ - PrivateKeyEd25519: Ed25519PrivateKey(privKey), - PublicCredentials: PublicCredentials{ - ID: GenerateUniqueID(), - PublicKeyEd25519: Ed25519PublicKey(pubKey), - }, - }, nil -} - -type SignedPlaintext struct { - Plaintext form.Bytes `json:"plaintext"` - Signature form.Bytes `json:"signature"` - PublicKeyEd25519 Ed25519PublicKey `json:"ed25519_public_key"` -} - -func (signed *SignedPlaintext) Verify() bool { - return ed25519.Verify(ed25519.PublicKey(signed.PublicKeyEd25519), signed.Plaintext, signed.Signature) -} - -func SignPlaintext(ctx context.Context, priv PrivateCredentials, plaintext []byte) SignedPlaintext { - signature := ed25519.Sign(ed25519.PrivateKey(priv.PrivateKeyEd25519), plaintext) - return SignedPlaintext{ - Plaintext: plaintext, - Signature: signature, - PublicKeyEd25519: priv.PublicCredentials.PublicKeyEd25519, - } -} - -func Sign[V form.Form](ctx context.Context, priv PrivateCredentials, value V) SignedPlaintext { - data, err := form.EncodeBytes(ctx, value) - must.NoError(ctx, err) - return SignPlaintext(ctx, priv, data) -} diff --git a/id/id.go b/id/id.go deleted file mode 100644 index 822f9ac..0000000 --- a/id/id.go +++ /dev/null @@ -1,34 +0,0 @@ -package id - -import ( - "context" - - "github.com/gov4git/lib4git/git" -) - -// PublicAddress points to the user's public repo. -type PublicAddress git.Address - -// PrivateAdress points to the user's private repo. -type PrivateAddress git.Address - -type OwnerAddress struct { - Public PublicAddress - Private PrivateAddress -} - -func Clone(ctx context.Context, addr PublicAddress) git.Cloned { - return git.CloneOne(ctx, git.Address(addr)) -} - -type OwnerCloned struct { - Public git.Cloned - Private git.Cloned -} - -func CloneOwner(ctx context.Context, ownerAddr OwnerAddress) OwnerCloned { - return OwnerCloned{ - Public: git.CloneOne(ctx, git.Address(ownerAddr.Public)), - Private: git.CloneOne(ctx, git.Address(ownerAddr.Private)), - } -} diff --git a/id/init.go b/id/init.go deleted file mode 100644 index d8d0b1c..0000000 --- a/id/init.go +++ /dev/null @@ -1,58 +0,0 @@ -package id - -import ( - "context" - - "github.com/gov4git/lib4git/form" - "github.com/gov4git/lib4git/git" - "github.com/gov4git/lib4git/must" -) - -func Init( - ctx context.Context, - ownerAddr OwnerAddress, -) git.Change[form.None, PrivateCredentials] { - ownerCloned := CloneOwner(ctx, ownerAddr) - privChg := InitLocal(ctx, ownerAddr, ownerCloned) - - ownerCloned.Public.Push(ctx) - ownerCloned.Private.Push(ctx) - return privChg -} - -func InitLocal( - ctx context.Context, - ownerAddr OwnerAddress, - ownerCloned OwnerCloned, -) git.Change[form.None, PrivateCredentials] { - - privChg := initPrivateStageOnly(ctx, ownerCloned.Private.Tree(), ownerAddr) - pubChg := initPublicStageOnly(ctx, ownerCloned.Public.Tree(), privChg.Result.PublicCredentials) - git.Commit(ctx, ownerCloned.Private.Tree(), privChg.Msg) - git.Commit(ctx, ownerCloned.Public.Tree(), pubChg.Msg) - return privChg -} - -func initPrivateStageOnly(ctx context.Context, priv *git.Tree, ownerAddr OwnerAddress) git.Change[form.None, PrivateCredentials] { - if _, err := priv.Filesystem.Stat(PrivateCredentialsNS.Path()); err == nil { - must.Errorf(ctx, "private credentials file already exists") - } - cred, err := GenerateCredentials() - must.NoError(ctx, err) - git.ToFileStage(ctx, priv, PrivateCredentialsNS.Path(), cred) - return git.NewChange( - "Initialized private credentials.", - "id_init_private", - form.None{}, - cred, - nil, - ) -} - -func initPublicStageOnly(ctx context.Context, pub *git.Tree, cred PublicCredentials) git.ChangeNoResult { - if _, err := pub.Filesystem.Stat(PublicCredentialsNS.Path()); err == nil { - must.Errorf(ctx, "public credentials file already exists") - } - git.ToFileStage(ctx, pub, PublicCredentialsNS.Path(), cred) - return git.NewChangeNoResult("Initialized public credentials.", "id_init_public") -} diff --git a/id/init_test.go b/id/init_test.go deleted file mode 100644 index fd57ee4..0000000 --- a/id/init_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package id - -import ( - "testing" - - "github.com/gov4git/lib4git/git" - "github.com/gov4git/lib4git/must" - "github.com/gov4git/lib4git/testutil" -) - -func TestInit(t *testing.T) { - ctx := testutil.NewCtx(t, false) - testID := NewTestID(ctx, t, git.MainBranch, true) - Init(ctx, testID.OwnerAddress()) - if err := must.Try(func() { Init(ctx, testID.OwnerAddress()) }); err == nil { - t.Fatal("second init must fail") - } -} diff --git a/id/private.go b/id/private.go deleted file mode 100644 index 1ae2f54..0000000 --- a/id/private.go +++ /dev/null @@ -1,20 +0,0 @@ -package id - -import ( - "context" - - "github.com/gov4git/lib4git/form" - "github.com/gov4git/lib4git/git" -) - -func FetchOwnerCredentials(ctx context.Context, addr OwnerAddress) PrivateCredentials { - return GetOwnerCredentials(ctx, CloneOwner(ctx, addr)) -} - -func GetOwnerCredentials(ctx context.Context, owner OwnerCloned) PrivateCredentials { - return GetPrivateCredentials(ctx, owner.Private.Tree()) -} - -func GetPrivateCredentials(ctx context.Context, privateTree *git.Tree) PrivateCredentials { - return form.FromFile[PrivateCredentials](ctx, privateTree.Filesystem, PrivateCredentialsNS.Path()) -} diff --git a/id/public.go b/id/public.go deleted file mode 100644 index 2980428..0000000 --- a/id/public.go +++ /dev/null @@ -1,16 +0,0 @@ -package id - -import ( - "context" - - "github.com/gov4git/lib4git/form" - "github.com/gov4git/lib4git/git" -) - -func FetchPublicCredentials(ctx context.Context, addr PublicAddress) PublicCredentials { - return GetPublicCredentials(ctx, git.CloneOne(ctx, git.Address(addr)).Tree()) -} - -func GetPublicCredentials(ctx context.Context, t *git.Tree) PublicCredentials { - return form.FromFile[PublicCredentials](ctx, t.Filesystem, PublicCredentialsNS.Path()) -} diff --git a/id/schema.go b/id/schema.go deleted file mode 100644 index 52f2e10..0000000 --- a/id/schema.go +++ /dev/null @@ -1,32 +0,0 @@ -package id - -import ( - "github.com/google/uuid" - "github.com/gov4git/lib4git/ns" -) - -var ( - PublicNS = ns.NS{"id"} - PrivateNS = ns.NS{"id"} -) - -var ( - PublicCredentialsNS = PublicNS.Sub("public_credentials.json") - PrivateCredentialsNS = PrivateNS.Sub("private_credentials.json") -) - -type ID string - -func GenerateUniqueID() ID { - return ID(uuid.New().String()) -} - -type PublicCredentials struct { - ID ID `json:"id"` - PublicKeyEd25519 Ed25519PublicKey `json:"public_key_ed25519"` -} - -type PrivateCredentials struct { - PrivateKeyEd25519 Ed25519PrivateKey `json:"private_key_ed25519"` - PublicCredentials PublicCredentials `json:"public_credentials"` -} diff --git a/id/test_id.go b/id/test_id.go deleted file mode 100644 index abff70a..0000000 --- a/id/test_id.go +++ /dev/null @@ -1,42 +0,0 @@ -package id - -import ( - "context" - "fmt" - "testing" - - "github.com/gov4git/lib4git/git" - "github.com/gov4git/lib4git/testutil" -) - -type TestID struct { - Public testutil.LocalAddress - Private testutil.LocalAddress -} - -func (x TestID) OwnerAddress() OwnerAddress { - return OwnerAddress{Public: x.PublicAddress(), Private: x.PrivateAddress()} -} - -func (x TestID) OwnerCloned() OwnerCloned { - return OwnerCloned{Public: x.Public, Private: x.Private} -} - -func (x TestID) PublicAddress() PublicAddress { - return PublicAddress(x.Public.Address()) -} - -func (x TestID) PrivateAddress() PrivateAddress { - return PrivateAddress(x.Private.Address()) -} - -func (x TestID) String() string { - return fmt.Sprintf("test identity, public_dir=%v private_dir=%v\n", x.Public.Dir(), x.Private.Dir()) -} - -func NewTestID(ctx context.Context, t *testing.T, branch git.Branch, isBare bool) TestID { - return TestID{ - Public: testutil.NewLocalAddress(ctx, t, branch, isBare), - Private: testutil.NewLocalAddress(ctx, t, branch, isBare), - } -} diff --git a/ns/ns.go b/ns/ns.go index 77f6474..8ccaa34 100644 --- a/ns/ns.go +++ b/ns/ns.go @@ -2,6 +2,7 @@ package ns import ( "path/filepath" + "slices" "strings" ) @@ -20,15 +21,19 @@ func Equal(a, b NS) bool { return true } -func ParseFromPath(p string) NS { - return strings.Split(filepath.Clean(p), string(filepath.Separator)) +func ParseFromOSPath(p string) NS { + return strings.Split(filepath.ToSlash(filepath.Clean(p)), "/") +} + +func ParseFromGitPath(p string) NS { + return strings.Split(p, "/") } func (ns NS) GitPath() string { return strings.Join(ns, "/") } -func (ns NS) Path() string { +func (ns NS) OSPath() string { return filepath.Join(ns...) } @@ -42,13 +47,14 @@ func (ns NS) Ext(ext string) NS { return xs } -func (ns NS) Sub(path string) NS { - sub := make(NS, len(ns)+1) - for i := range ns { - sub[i] = ns[i] - } - sub[len(ns)] = path - return sub +// Deprecated: Use Append. +func (ns NS) Sub(pathElem string) NS { + return ns.Append(pathElem) +} + +func (ns NS) Append(elems ...string) NS { + r := slices.Clone(ns) + return append(r, elems...) } func (ns NS) Join(sub NS) NS { @@ -61,3 +67,21 @@ func (ns NS) Join(sub NS) NS { func (ns NS) Parts() []string { return ns } + +func (ns NS) Base() string { + if len(ns) == 0 { + return "" + } + return ns[len(ns)-1] +} + +func (ns NS) Dir() NS { + if len(ns) == 0 { + return NS{} + } + return ns[:len(ns)-1] +} + +func (ns NS) Len() int { + return len(ns) +}