diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index e61af21..99b495e 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -12,7 +12,10 @@ on: jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] steps: - name: Checkout uses: actions/checkout@v4 @@ -20,7 +23,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.20' + go-version: '1.20.x' - name: Build utilities run: | diff --git a/cmd/build/build.go b/cmd/build/build.go index d97d46c..2f6f3b0 100644 --- a/cmd/build/build.go +++ b/cmd/build/build.go @@ -4,13 +4,13 @@ import ( "log" "os" - "github.com/schwarzlichtbezirk/wpk" lw "github.com/schwarzlichtbezirk/wpk/luawpk" + "github.com/schwarzlichtbezirk/wpk/util" ) func main() { for _, fpath := range os.Args[1:] { - if err := lw.RunLuaVM(wpk.Envfmt(fpath, nil)); err != nil { + if err := lw.RunLuaVM(util.Envfmt(fpath, nil)); err != nil { log.Println(err.Error()) return } diff --git a/cmd/extract/extract.go b/cmd/extract/extract.go index 2b9d85b..84d5519 100644 --- a/cmd/extract/extract.go +++ b/cmd/extract/extract.go @@ -13,6 +13,7 @@ import ( "github.com/schwarzlichtbezirk/wpk/bulk" "github.com/schwarzlichtbezirk/wpk/fsys" "github.com/schwarzlichtbezirk/wpk/mmap" + "github.com/schwarzlichtbezirk/wpk/util" ) // command line settings @@ -49,7 +50,7 @@ func checkargs() int { if fpath == "" { continue } - fpath = wpk.ToSlash(wpk.Envfmt(fpath, nil)) + fpath = util.ToSlash(util.Envfmt(fpath, nil)) if ok, _ := wpk.FileExists(fpath); !ok { log.Printf("source file #%d '%s' does not exist", i+1, fpath) ec++ @@ -62,7 +63,7 @@ func checkargs() int { ec++ } - DstPath = wpk.ToSlash(wpk.Envfmt(DstPath, nil)) + DstPath = util.ToSlash(util.Envfmt(DstPath, nil)) if DstPath == "" { log.Println("destination path does not specified") ec++ @@ -133,7 +134,7 @@ func readpackage() (err error) { next = err == nil }() - var fullpath = wpk.JoinPath(DstPath, fkey) + var fullpath = util.JoinPath(DstPath, fkey) if err = os.MkdirAll(path.Dir(fullpath), os.ModePerm); err != nil { return } diff --git a/cmd/pack/pack.go b/cmd/pack/pack.go index da51446..ed3d4c2 100644 --- a/cmd/pack/pack.go +++ b/cmd/pack/pack.go @@ -13,6 +13,7 @@ import ( "strings" "github.com/schwarzlichtbezirk/wpk" + "github.com/schwarzlichtbezirk/wpk/util" ) // command line settings @@ -41,7 +42,7 @@ func checkargs() (ec int) { // returns error counter if fpath == "" { continue } - fpath = wpk.ToSlash(wpk.Envfmt(fpath, nil)) + fpath = util.ToSlash(util.Envfmt(fpath, nil)) if !strings.HasSuffix(fpath, "/") { fpath += "/" } @@ -57,7 +58,7 @@ func checkargs() (ec int) { // returns error counter ec++ } - DstFile = wpk.ToSlash(wpk.Envfmt(DstFile, nil)) + DstFile = util.ToSlash(util.Envfmt(DstFile, nil)) if DstFile == "" { log.Println("destination file does not specified") ec++ @@ -118,7 +119,7 @@ func writepackage() (err error) { return nil // file is directory } - var fpath = wpk.JoinPath(srcpath, fkey) + var fpath = util.JoinPath(srcpath, fkey) var file wpk.RFile var ts wpk.TagsetRaw if file, err = os.Open(fpath); err != nil { diff --git a/dir.go b/dir.go index 26538a9..bb0c918 100644 --- a/dir.go +++ b/dir.go @@ -7,6 +7,8 @@ import ( "os" "path" "strings" + + "github.com/schwarzlichtbezirk/wpk/util" ) // MakeTagsPath receives file path and returns it with ".wpt" extension. @@ -76,13 +78,13 @@ func FileExists(fpath string) (bool, error) { // TempPath returns filename located at temporary directory. func TempPath(fname string) string { - return JoinPath(ToSlash(os.TempDir()), fname) + return util.JoinPath(util.ToSlash(os.TempDir()), fname) } // ReadDirN returns fs.DirEntry array with nested into given package directory presentation. // It's core function for ReadDirFile and ReadDirFS structures. func (ftt *FTT) ReadDirN(fulldir string, n int) (list []fs.DirEntry, err error) { - fulldir = ToSlash(fulldir) + fulldir = util.ToSlash(fulldir) var found = map[string]fs.DirEntry{} var prefix string if fulldir != "." && fulldir != "" { @@ -97,7 +99,7 @@ func (ftt *FTT) ReadDirN(fulldir string, n int) (list []fs.DirEntry, err error) found[suffix] = ts n-- } else { // dir detected - var subdir = JoinPath(prefix, suffix[:sp]) + var subdir = util.JoinPath(prefix, suffix[:sp]) if _, ok := found[subdir]; !ok { var dts = TagsetRaw{}. Put(TIDpath, StrTag(subdir)) @@ -128,7 +130,7 @@ func (ftt *FTT) ReadDirN(fulldir string, n int) (list []fs.DirEntry, err error) // OpenDir returns PackDirFile structure associated with group of files in package // pooled with common directory prefix. Usable to implement fs.FileSystem interface. func (ftt *FTT) OpenDir(fulldir string) (fs.ReadDirFile, error) { - fulldir = ToSlash(fulldir) + fulldir = util.ToSlash(fulldir) var prefix string if fulldir != "." && fulldir != "" { prefix = fulldir + "/" // set terminated slash diff --git a/go.mod b/go.mod index 5072a1c..475cdbf 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/schwarzlichtbezirk/wpk go 1.20 require ( - github.com/edsrzf/mmap-go v1.1.0 + github.com/edsrzf/mmap-go v1.2.0 github.com/h2non/filetype v1.1.3 github.com/yuin/gopher-lua v1.1.1 gopkg.in/djherbis/times.v1 v1.3.0 diff --git a/go.sum b/go.sum index a4f45cb..7e16fe2 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ= -github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= +github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84= +github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= diff --git a/luawpk/adjusttags.go b/luawpk/adjusttags.go index 8067ab7..e716808 100644 --- a/luawpk/adjusttags.go +++ b/luawpk/adjusttags.go @@ -13,7 +13,9 @@ import ( "path" "github.com/h2non/filetype" + "github.com/schwarzlichtbezirk/wpk" + "github.com/schwarzlichtbezirk/wpk/util" ) func adjustmime(ts wpk.TagsetRaw, r io.ReadSeeker, skip bool) (wpk.TagsetRaw, error) { @@ -22,7 +24,7 @@ func adjustmime(ts wpk.TagsetRaw, r io.ReadSeeker, skip bool) (wpk.TagsetRaw, er if skip || ts.Has(wpk.TIDmime) { return ts, err } - var ext = wpk.ToLower(path.Ext(ts.Path())) + var ext = util.ToLower(path.Ext(ts.Path())) var ctype string if ctype = mime.TypeByExtension(ext); ctype == "" { if ctype, ok = MimeExt[ext]; !ok { diff --git a/luawpk/luapath.go b/luawpk/luapath.go index 238bed1..ae9f989 100644 --- a/luawpk/luapath.go +++ b/luawpk/luapath.go @@ -5,8 +5,9 @@ import ( "path" "path/filepath" - "github.com/schwarzlichtbezirk/wpk" lua "github.com/yuin/gopher-lua" + + "github.com/schwarzlichtbezirk/wpk/util" ) // RegPath registers "path" namespace into Lua virtual machine. @@ -34,7 +35,7 @@ var pathfuncs = map[string]lua.LGFunction{ func pathtoslash(ls *lua.LState) int { var fpath = ls.CheckString(1) - ls.Push(lua.LString(wpk.ToSlash(fpath))) + ls.Push(lua.LString(util.ToSlash(fpath))) return 1 } @@ -73,7 +74,7 @@ func pathbase(ls *lua.LState) int { func pathname(ls *lua.LState) int { var fpath = ls.CheckString(1) - var name = wpk.PathName(fpath) + var name = util.PathName(fpath) ls.Push(lua.LString(name)) return 1 } @@ -128,7 +129,7 @@ func pathglob(ls *lua.LState) int { return 0 } for _, dir := range matches { - ls.Push(lua.LString(wpk.ToSlash(dir))) + ls.Push(lua.LString(util.ToSlash(dir))) } return len(matches) } @@ -160,7 +161,7 @@ func pathenum(ls *lua.LState) int { func pathenvfmt(ls *lua.LState) int { var fpath = ls.CheckString(1) - ls.Push(lua.LString(wpk.Envfmt(fpath, nil))) + ls.Push(lua.LString(util.Envfmt(fpath, nil))) return 1 } diff --git a/luawpk/luawpk.go b/luawpk/luawpk.go index 94d4ac8..7ed474b 100644 --- a/luawpk/luawpk.go +++ b/luawpk/luawpk.go @@ -8,8 +8,9 @@ import ( "path" "strings" - "github.com/schwarzlichtbezirk/wpk" lua "github.com/yuin/gopher-lua" + + "github.com/schwarzlichtbezirk/wpk" ) // Package writer errors. diff --git a/luawpk/nametid.go b/luawpk/nametid.go index 55cf9fa..07a38b0 100644 --- a/luawpk/nametid.go +++ b/luawpk/nametid.go @@ -7,8 +7,9 @@ import ( "strconv" "time" - "github.com/schwarzlichtbezirk/wpk" lua "github.com/yuin/gopher-lua" + + "github.com/schwarzlichtbezirk/wpk" ) const ( diff --git a/luawpk/runlvm.go b/luawpk/runlvm.go index 871baf6..12ab265 100644 --- a/luawpk/runlvm.go +++ b/luawpk/runlvm.go @@ -9,8 +9,9 @@ import ( "path" "time" - "github.com/schwarzlichtbezirk/wpk" lua "github.com/yuin/gopher-lua" + + "github.com/schwarzlichtbezirk/wpk/util" ) var ( @@ -51,7 +52,7 @@ func luacheckfile(ls *lua.LState) int { func luabin2hex(ls *lua.LState) int { var arg = ls.CheckString(1) - ls.Push(lua.LString(hex.EncodeToString(wpk.S2B(arg)))) + ls.Push(lua.LString(hex.EncodeToString(util.S2B(arg)))) return 1 } @@ -67,7 +68,7 @@ func luahex2bin(ls *lua.LState) int { if b, err = hex.DecodeString(arg); err != nil { return 0 } - ls.Push(lua.LString(wpk.B2S(b))) + ls.Push(lua.LString(util.B2S(b))) return 1 } @@ -106,9 +107,9 @@ func InitLuaVM(ls *lua.LState) { var bindir = func() string { if str, err := os.Executable(); err == nil { - return path.Dir(wpk.ToSlash(str)) + return path.Dir(util.ToSlash(str)) } else { - return path.Dir(wpk.ToSlash(os.Args[0])) + return path.Dir(util.ToSlash(os.Args[0])) } }() @@ -116,7 +117,7 @@ func InitLuaVM(ls *lua.LState) { ls.SetGlobal("buildvers", lua.LString(BuildVers)) ls.SetGlobal("buildtime", lua.LString(BuildTime)) ls.SetGlobal("bindir", lua.LString(bindir)) - ls.SetGlobal("tmpdir", lua.LString(wpk.ToSlash(os.TempDir()))) + ls.SetGlobal("tmpdir", lua.LString(util.ToSlash(os.TempDir()))) // global functions ls.SetGlobal("log", ls.NewFunction(lualog)) ls.SetGlobal("checkfile", ls.NewFunction(luacheckfile)) @@ -132,7 +133,7 @@ func RunLuaVM(fpath string) (err error) { defer ls.Close() InitLuaVM(ls) - var scrdir = path.Dir(wpk.ToSlash(fpath)) + var scrdir = path.Dir(util.ToSlash(fpath)) ls.SetGlobal("scrdir", lua.LString(scrdir)) if err = ls.DoFile(fpath); err != nil { diff --git a/tagset.go b/tagset.go index d44a329..115386f 100644 --- a/tagset.go +++ b/tagset.go @@ -5,6 +5,8 @@ import ( "io/fs" "path" "time" + + "github.com/schwarzlichtbezirk/wpk/util" ) var ( @@ -17,12 +19,12 @@ type TagRaw []byte // TagStr tag converter. func (t TagRaw) TagStr() (string, bool) { - return B2S(t), true + return util.B2S(t), true } // StrTag is string tag constructor. func StrTag(val string) TagRaw { - return S2B(val) + return util.S2B(val) } // TagBool is boolean tag converter. @@ -59,7 +61,7 @@ func ByteTag(val byte) TagRaw { // TagUint16 is 16-bit unsigned int tag converter. func (t TagRaw) TagUint16() (uint16, bool) { if len(t) == 2 { - return GetU16(t), true + return util.GetU16(t), true } return 0, false } @@ -67,14 +69,14 @@ func (t TagRaw) TagUint16() (uint16, bool) { // Uint16Tag is 16-bit unsigned int tag constructor. func Uint16Tag(val uint16) TagRaw { var buf [2]byte - SetU16(buf[:], val) + util.SetU16(buf[:], val) return buf[:] } // TagUint32 is 32-bit unsigned int tag converter. func (t TagRaw) TagUint32() (uint32, bool) { if len(t) == 4 { - return GetU32(t), true + return util.GetU32(t), true } return 0, false } @@ -82,14 +84,14 @@ func (t TagRaw) TagUint32() (uint32, bool) { // Uint32Tag is 32-bit unsigned int tag constructor. func Uint32Tag(val uint32) TagRaw { var buf [4]byte - SetU32(buf[:], val) + util.SetU32(buf[:], val) return buf[:] } // TagUint64 is 64-bit unsigned int tag converter. func (t TagRaw) TagUint64() (uint64, bool) { if len(t) == 8 { - return GetU64(t), true + return util.GetU64(t), true } return 0, false } @@ -97,7 +99,7 @@ func (t TagRaw) TagUint64() (uint64, bool) { // Uint64Tag is 64-bit unsigned int tag constructor. func Uint64Tag(val uint64) TagRaw { var buf [8]byte - SetU64(buf[:], val) + util.SetU64(buf[:], val) return buf[:] } @@ -105,11 +107,11 @@ func Uint64Tag(val uint64) TagRaw { func (t TagRaw) TagUint() (uint, bool) { switch len(t) { case 8: - return uint(GetU64(t)), true + return uint(util.GetU64(t)), true case 4: - return uint(GetU32(t)), true + return uint(util.GetU32(t)), true case 2: - return uint(GetU16(t)), true + return uint(util.GetU16(t)), true case 1: return uint(t[0]), true } @@ -121,15 +123,15 @@ func UintTag(val uint) TagRaw { switch { case val > 0xffffffff: var buf [8]byte - SetU64(buf[:], uint64(val)) + util.SetU64(buf[:], uint64(val)) return buf[:] case val > 0xffff: var buf [4]byte - SetU32(buf[:], uint32(val)) + util.SetU32(buf[:], uint32(val)) return buf[:] case val > 0xff: var buf [2]byte - SetU16(buf[:], uint16(val)) + util.SetU16(buf[:], uint16(val)) return buf[:] default: var buf [1]byte @@ -143,15 +145,15 @@ func UintLenTag(val uint, l int) TagRaw { switch l { case 8: var buf [8]byte - SetU64(buf[:], uint64(val)) + util.SetU64(buf[:], uint64(val)) return buf[:] case 4: var buf [4]byte - SetU32(buf[:], uint32(val)) + util.SetU32(buf[:], uint32(val)) return buf[:] case 2: var buf [2]byte - SetU16(buf[:], uint16(val)) + util.SetU16(buf[:], uint16(val)) return buf[:] case 1: var buf [1]byte @@ -165,7 +167,7 @@ func UintLenTag(val uint, l int) TagRaw { // TagNumber is 64-bit float tag converter. func (t TagRaw) TagNumber() (float64, bool) { if len(t) == 8 { - return GetF64(t), true + return util.GetF64(t), true } return 0, false } @@ -173,7 +175,7 @@ func (t TagRaw) TagNumber() (float64, bool) { // NumberTag is 64-bit float tag constructor. func NumberTag(val float64) TagRaw { var buf [8]byte - SetF64(buf[:], val) + util.SetF64(buf[:], val) return buf[:] } @@ -181,11 +183,11 @@ func NumberTag(val float64) TagRaw { func (t TagRaw) TagTime() (time.Time, bool) { switch len(t) { case 8: - var milli = int64(GetU64(t)) + var milli = int64(util.GetU64(t)) return time.Unix(milli/1000, (milli%1000)*1000000), true case 12: - var sec = int64(GetU64(t[:8])) - var nsec = int64(GetU32(t[8:])) + var sec = int64(util.GetU64(t[:8])) + var nsec = int64(util.GetU32(t[8:])) return time.Unix(sec, nsec), true } return time.Time{}, false @@ -195,10 +197,10 @@ func (t TagRaw) TagTime() (time.Time, bool) { func (t TagRaw) TagUnixms() (int64, bool) { switch len(t) { case 8: - return int64(GetU64(t)), true + return int64(util.GetU64(t)), true case 12: - var sec = int64(GetU64(t[:8])) - var nsec = int64(GetU32(t[8:])) + var sec = int64(util.GetU64(t[:8])) + var nsec = int64(util.GetU32(t[8:])) return time.Unix(sec, nsec).UnixMilli(), true } return 0, false @@ -207,15 +209,15 @@ func (t TagRaw) TagUnixms() (int64, bool) { // UnixmsTag is 8-bytes UNIX time in milliseconds tag constructor. func UnixmsTag(val time.Time) TagRaw { var buf [8]byte - SetU64(buf[:], uint64(val.UnixMilli())) + util.SetU64(buf[:], uint64(val.UnixMilli())) return buf[:] } // TimeTag is 12-bytes UNIX time tag constructor. func TimeTag(val time.Time) TagRaw { var buf [12]byte - SetU64(buf[:8], uint64(val.Unix())) - SetU32(buf[8:], uint32(val.Nanosecond())) + util.SetU64(buf[:8], uint64(val.Unix())) + util.SetU32(buf[8:], uint32(val.Nanosecond())) return buf[:] } @@ -268,8 +270,8 @@ const taghdrsz = PTStidsz + PTStagsz // Can be used in chain calls at initialization. func (ts TagsetRaw) Put(tid TID, tag TagRaw) TagsetRaw { var buf = make([]byte, taghdrsz+len(tag)) - SetU16(buf, tid) - SetU16(buf[PTStidsz:], uint16(len(tag))) + util.SetU16(buf, tid) + util.SetU16(buf[PTStidsz:], uint16(len(tag))) copy(buf[taghdrsz:], tag) ts = append(ts, buf...) return ts @@ -315,7 +317,7 @@ func (ts TagsetRaw) SetOk(tid TID, tag TagRaw) (TagsetRaw, bool) { if tl == uint16(tsi.pos-tsi.tag) { copy(ts[tsi.tag:tsi.pos], tag) } else { - SetU16(ts[tsi.tag-PTStagsz:tsi.tag], tl) // set tag length + util.SetU16(ts[tsi.tag-PTStagsz:tsi.tag], tl) // set tag length var suff = ts[tsi.pos:] ts = append(ts[:tsi.tag], tag...) ts = append(ts, suff...) @@ -602,13 +604,13 @@ func (tsi *TagsetIterator) Next() (ok bool) { if tsi.pos += PTStidsz; tsi.pos > tsl { return } - var tid = GetU16(tsi.TagsetRaw[tsi.pos-PTStidsz : tsi.pos]) + var tid = util.GetU16(tsi.TagsetRaw[tsi.pos-PTStidsz : tsi.pos]) // get tag length if tsi.pos += PTStagsz; tsi.pos > tsl { return } - var len = GetU16(tsi.TagsetRaw[tsi.pos-PTStagsz : tsi.pos]) + var len = util.GetU16(tsi.TagsetRaw[tsi.pos-PTStagsz : tsi.pos]) // store tag content position var tag = tsi.pos diff --git a/tagset_test.go b/tagset_test.go index 7332928..3ff8bb9 100644 --- a/tagset_test.go +++ b/tagset_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/schwarzlichtbezirk/wpk" + "github.com/schwarzlichtbezirk/wpk/util" ) func TestTagset(t *testing.T) { @@ -22,7 +23,7 @@ func TestTagset(t *testing.T) { var ts = wpk.TagsetRaw{}. Put(wpk.TIDoffset, wpk.UintTag(offset)). Put(wpk.TIDsize, wpk.UintTag(size)). - Put(wpk.TIDpath, wpk.StrTag(wpk.ToSlash(fkey1))). + Put(wpk.TIDpath, wpk.StrTag(util.ToSlash(fkey1))). Put(wpk.TIDfid, wpk.UintTag(fid)) var tsi = ts.Iterator() @@ -41,8 +42,8 @@ func TestTagset(t *testing.T) { } } - assert(wpk.ToSlash(fkey1) == fkey, "toslash test failed") - assert(wpk.ToSlash(fkey2) == fkey, "toslash test failed") + assert(util.ToSlash(fkey1) == fkey, "toslash test failed") + assert(util.ToSlash(fkey2) == fkey, "toslash test failed") assert(tsi.TID() == wpk.TIDnone, "tag ID in created iterator should be 'none'") assert(ts.Num() == 4, "wrong number of tags") @@ -108,7 +109,7 @@ func TestTagset(t *testing.T) { ts, ok = ts.SetOk(wpk.TIDpath, wpk.StrTag(fkey)) assert(!ok, "content of 'path' tag should be replaced by 'Set'") assert(ts.Num() == 4, "number of tags after replace 'path' must not be changed") - assert(ts.Path() == wpk.ToSlash(fkey2), "'Set' function does not work correctly") + assert(ts.Path() == util.ToSlash(fkey2), "'Set' function does not work correctly") ts, ok = ts.SetOk(wpk.TIDmime, wpk.StrTag(mime)) assert(ok, "content of 'mime' tag should be added by 'Set'") assert(ts.Num() == 4+1, "number of tags after add 'mime' must be added by one") diff --git a/testdata/api.lua b/testdata/api.lua index cd7e370..2dbae48 100644 --- a/testdata/api.lua +++ b/testdata/api.lua @@ -244,7 +244,7 @@ function wpk.create(fpath)-- additional wpk-constructor pkg.autofid = true -- put auto generated file ID for each file pkg.automime = true -- put MIME type for each file if it is not given explicit pkg.crc32 = true -- generate CRC32 Castagnoli code for each file - pkg:begin(path.toslash(fpath)) -- open wpk-file for write + pkg:begin(fpath) -- open wpk-file for write log("starts: "..pkg.pkgpath) return pkg end @@ -271,7 +271,7 @@ logfmt("script dir: %s", scrdir) logfmt("temporary dir: %s", tmpdir) -- starts new package at golang binary directory -local pkg = wpk.create(path.envfmt"${GOPATH}/bin/api.wpk") +local pkg = wpk.create(path.toslash(path.envfmt"${GOPATH}/bin/api.wpk")) pkg.label = "api-sample" -- image label pkg.secret = "package-private-key" -- private key to sign cryptographic hashes for each file pkg.sha224 = true -- generate SHA224 hash for each file diff --git a/union.go b/union.go index 24a5b50..9984f15 100644 --- a/union.go +++ b/union.go @@ -6,6 +6,8 @@ import ( "path" "strconv" "strings" + + "github.com/schwarzlichtbezirk/wpk/util" ) // Void is empty structure to release of the set of keys. @@ -109,7 +111,7 @@ func (u *Union) Stat(fpath string) (fs.FileInfo, error) { // Glob returns the names of all files in union matching pattern or nil // if there is no matching file. func (u *Union) Glob(pattern string) (res []string, err error) { - pattern = ToSlash(pattern) + pattern = util.ToSlash(pattern) if _, err = path.Match(pattern, ""); err != nil { return } @@ -152,7 +154,7 @@ func (u *Union) ReadFile(fpath string) ([]byte, error) { // ReadDir reads the named directory // and returns a list of directory entries sorted by filename. func (u *Union) ReadDirN(dir string, n int) (list []fs.DirEntry, err error) { - dir = ToSlash(dir) + dir = util.ToSlash(dir) var found = map[string]fs.DirEntry{} var ni = n for _, pkg := range u.List { @@ -170,7 +172,7 @@ func (u *Union) ReadDirN(dir string, n int) (list []fs.DirEntry, err error) { found[suffix] = ts ni-- } else { // dir detected - var subdir = JoinPath(prefix, suffix[:sp]) + var subdir = util.JoinPath(prefix, suffix[:sp]) if _, ok := found[subdir]; !ok { var dts = TagsetRaw{}. Put(TIDpath, StrTag(subdir)) @@ -214,7 +216,7 @@ func (u *Union) ReadDir(dir string) ([]fs.DirEntry, error) { // If union have more than one file with the same name, first will be returned. // fs.FS implementation. func (u *Union) Open(dir string) (fs.File, error) { - dir = ToSlash(dir) + dir = util.ToSlash(dir) if len(u.List) == 0 { return nil, &fs.PathError{Op: "open", Path: dir, Err: fs.ErrNotExist} } diff --git a/union_test.go b/union_test.go index 87b7955..5028414 100644 --- a/union_test.go +++ b/union_test.go @@ -9,6 +9,7 @@ import ( "github.com/schwarzlichtbezirk/wpk" "github.com/schwarzlichtbezirk/wpk/bulk" "github.com/schwarzlichtbezirk/wpk/mmap" + "github.com/schwarzlichtbezirk/wpk/util" ) var testpack1 = wpk.TempPath("testpack1.wpk") @@ -123,7 +124,7 @@ func TestUnion(t *testing.T) { var delist, _ = df.ReadDir(-1) list = make([]string, len(delist)) for i, de := range delist { - list[i] = wpk.JoinPath(fpath, de.Name()) + list[i] = util.JoinPath(fpath, de.Name()) } } else { t.Fatalf("cannot cast '%s' directory property to fs.ReadDirFile", fpath) @@ -218,7 +219,7 @@ func TestUnion(t *testing.T) { // ReadFile test // - var imgfpath = wpk.JoinPath(mediadir, "img1/Qarataşlar.jpg") + var imgfpath = util.JoinPath(mediadir, "img1/Qarataşlar.jpg") var imgb, pkgb []byte if imgb, err = os.ReadFile(imgfpath); err != nil { t.Fatal(err) diff --git a/seqmap.go b/util/seqmap.go similarity index 99% rename from seqmap.go rename to util/seqmap.go index ff4ba43..4479db5 100644 --- a/seqmap.go +++ b/util/seqmap.go @@ -1,4 +1,4 @@ -package wpk +package util import ( "sync" diff --git a/strutil.go b/util/strutil.go similarity index 99% rename from strutil.go rename to util/strutil.go index f972881..8f3985e 100644 --- a/strutil.go +++ b/util/strutil.go @@ -1,4 +1,4 @@ -package wpk +package util import ( "os" diff --git a/strutil_test.go b/util/strutil_test.go similarity index 53% rename from strutil_test.go rename to util/strutil_test.go index e09f193..39c5efe 100644 --- a/strutil_test.go +++ b/util/strutil_test.go @@ -1,4 +1,4 @@ -package wpk_test +package util_test import ( "fmt" @@ -6,7 +6,7 @@ import ( "testing" "unsafe" - "github.com/schwarzlichtbezirk/wpk" + "github.com/schwarzlichtbezirk/wpk/util" ) func TestS2B(t *testing.T) { @@ -17,7 +17,7 @@ func TestS2B(t *testing.T) { if ps == pb { t.Error("string pointer is equal to pointer on new allocated bytes slice") }*/ - var b = wpk.S2B(s) + var b = util.S2B(s) var pb = unsafe.Pointer(unsafe.SliceData(b)) if ps != pb { t.Error("string pointer is not equal to pointer on same bytes slice") @@ -32,7 +32,7 @@ func TestB2S(t *testing.T) { if pb == ps { t.Error("bytes slice pointer is equal to pointer on new allocated string") } - s = wpk.B2S(b) + s = util.B2S(b) ps = unsafe.Pointer(unsafe.StringData(s)) if pb != ps { t.Error("bytes slice pointer is not equal to pointer on same string") @@ -40,30 +40,30 @@ func TestB2S(t *testing.T) { } func ExampleToSlash() { - fmt.Println(wpk.ToSlash("C:\\Windows\\Temp")) + fmt.Println(util.ToSlash("C:\\Windows\\Temp")) // Output: C:/Windows/Temp } func ExampleToLower() { - fmt.Println(wpk.ToLower("C:\\Windows\\Temp")) + fmt.Println(util.ToLower("C:\\Windows\\Temp")) // Output: c:\windows\temp } func ExampleToUpper() { - fmt.Println(wpk.ToUpper("C:\\Windows\\Temp")) + fmt.Println(util.ToUpper("C:\\Windows\\Temp")) // Output: C:\WINDOWS\TEMP } func ExampleToKey() { - fmt.Println(wpk.ToKey("C:\\Windows\\Temp")) + fmt.Println(util.ToKey("C:\\Windows\\Temp")) // Output: c:/windows/temp } func ExampleJoinPath() { - fmt.Println(wpk.JoinPath("dir", "base.ext")) - fmt.Println(wpk.JoinPath("dir/", "base.ext")) - fmt.Println(wpk.JoinPath("dir", "/base.ext")) - fmt.Println(wpk.JoinPath("dir/", "/base.ext")) + fmt.Println(util.JoinPath("dir", "base.ext")) + fmt.Println(util.JoinPath("dir/", "base.ext")) + fmt.Println(util.JoinPath("dir", "/base.ext")) + fmt.Println(util.JoinPath("dir/", "/base.ext")) // Output: // dir/base.ext // dir/base.ext @@ -72,9 +72,9 @@ func ExampleJoinPath() { } func ExampleJoinFilePath() { - fmt.Println(wpk.JoinFilePath("dir/", "base.ext")) - fmt.Println(wpk.JoinFilePath("dir", "/base.ext")) - fmt.Println(wpk.JoinFilePath("dir/", "/base.ext")) + fmt.Println(util.JoinFilePath("dir/", "base.ext")) + fmt.Println(util.JoinFilePath("dir", "/base.ext")) + fmt.Println(util.JoinFilePath("dir/", "/base.ext")) // Output: // dir/base.ext // dir/base.ext @@ -82,12 +82,12 @@ func ExampleJoinFilePath() { } func ExamplePathName() { - fmt.Println(wpk.PathName("C:\\Windows\\system.ini")) - fmt.Println(wpk.PathName("/go/bin/wpkbuild_win_x64.exe")) - fmt.Println(wpk.PathName("wpkbuild_win_x64.exe")) - fmt.Println(wpk.PathName("/go/bin/wpkbuild_linux_x64")) - fmt.Println(wpk.PathName("wpkbuild_linux_x64")) - fmt.Printf("'%s'\n", wpk.PathName("/go/bin/")) + fmt.Println(util.PathName("C:\\Windows\\system.ini")) + fmt.Println(util.PathName("/go/bin/wpkbuild_win_x64.exe")) + fmt.Println(util.PathName("wpkbuild_win_x64.exe")) + fmt.Println(util.PathName("/go/bin/wpkbuild_linux_x64")) + fmt.Println(util.PathName("wpkbuild_linux_x64")) + fmt.Printf("'%s'\n", util.PathName("/go/bin/")) // Output: // system // wpkbuild_win_x64 @@ -100,20 +100,20 @@ func ExamplePathName() { func ExampleEnvfmt() { os.Setenv("VAR", "/go") // successful patterns - fmt.Println(wpk.Envfmt("$VAR/bin/", nil)) - fmt.Println(wpk.Envfmt("${VAR}/bin/", nil)) - fmt.Println(wpk.Envfmt("%VAR%/bin/", nil)) - fmt.Println(wpk.Envfmt("/home$VAR", nil)) - fmt.Println(wpk.Envfmt("/home%VAR%", map[string]string{"VAR": "/any/path"})) - fmt.Println(wpk.Envfmt("$VAR%VAR%${VAR}", nil)) + fmt.Println(util.Envfmt("$VAR/bin/", nil)) + fmt.Println(util.Envfmt("${VAR}/bin/", nil)) + fmt.Println(util.Envfmt("%VAR%/bin/", nil)) + fmt.Println(util.Envfmt("/home$VAR", nil)) + fmt.Println(util.Envfmt("/home%VAR%", map[string]string{"VAR": "/any/path"})) + fmt.Println(util.Envfmt("$VAR%VAR%${VAR}", nil)) // patterns with unknown variable - fmt.Println(wpk.Envfmt("$VYR/bin/", nil)) - fmt.Println(wpk.Envfmt("${VAR}/${_foo_}", nil)) + fmt.Println(util.Envfmt("$VYR/bin/", nil)) + fmt.Println(util.Envfmt("${VAR}/${_foo_}", nil)) // patterns with errors - fmt.Println(wpk.Envfmt("$VAR$/bin/", nil)) - fmt.Println(wpk.Envfmt("${VAR/bin/", nil)) - fmt.Println(wpk.Envfmt("%VAR/bin/", nil)) - fmt.Println(wpk.Envfmt("/home${VAR", nil)) + fmt.Println(util.Envfmt("$VAR$/bin/", nil)) + fmt.Println(util.Envfmt("${VAR/bin/", nil)) + fmt.Println(util.Envfmt("%VAR/bin/", nil)) + fmt.Println(util.Envfmt("/home${VAR", nil)) // Output: // /go/bin/ // /go/bin/ diff --git a/uintio.go b/util/uintio.go similarity index 99% rename from uintio.go rename to util/uintio.go index 1aa6292..31112b3 100644 --- a/uintio.go +++ b/util/uintio.go @@ -1,4 +1,4 @@ -package wpk +package util import ( "io" diff --git a/wpk.go b/wpk.go index 0f94b3c..a5cb640 100644 --- a/wpk.go +++ b/wpk.go @@ -9,6 +9,8 @@ import ( "path" "strings" "sync" + + "github.com/schwarzlichtbezirk/wpk/util" ) const ( @@ -157,14 +159,14 @@ func (hdr *Header) DataSize() uint { // IsReady determines that package is ready for read the data. func (hdr *Header) IsReady() error { // can not read file tags table for opened on write single-file package. - if B2S(hdr.signature[:]) == SignBuild { + if util.B2S(hdr.signature[:]) == SignBuild { if hdr.datoffset != 0 { return ErrSignPre } return nil } // can not read file tags table on any incorrect signature - if B2S(hdr.signature[:]) != SignReady { + if util.B2S(hdr.signature[:]) != SignReady { return ErrSignBad } return nil @@ -179,15 +181,15 @@ func (hdr *Header) Parse(buf []byte) (n int64, err error) { } copy(hdr.signature[:], buf) n += SignSize - hdr.fttcount = GetU64(buf[n:]) + hdr.fttcount = util.GetU64(buf[n:]) n += 8 - hdr.fttoffset = GetU64(buf[n:]) + hdr.fttoffset = util.GetU64(buf[n:]) n += 8 - hdr.fttsize = GetU64(buf[n:]) + hdr.fttsize = util.GetU64(buf[n:]) n += 8 - hdr.datoffset = GetU64(buf[n:]) + hdr.datoffset = util.GetU64(buf[n:]) n += 8 - hdr.datsize = GetU64(buf[n:]) + hdr.datsize = util.GetU64(buf[n:]) n += 8 return } @@ -198,23 +200,23 @@ func (hdr *Header) ReadFrom(r io.Reader) (n int64, err error) { return } n += SignSize - if hdr.fttcount, err = ReadU64(r); err != nil { + if hdr.fttcount, err = util.ReadU64(r); err != nil { return } n += 8 - if hdr.fttoffset, err = ReadU64(r); err != nil { + if hdr.fttoffset, err = util.ReadU64(r); err != nil { return } n += 8 - if hdr.fttsize, err = ReadU64(r); err != nil { + if hdr.fttsize, err = util.ReadU64(r); err != nil { return } n += 8 - if hdr.datoffset, err = ReadU64(r); err != nil { + if hdr.datoffset, err = util.ReadU64(r); err != nil { return } n += 8 - if hdr.datsize, err = ReadU64(r); err != nil { + if hdr.datsize, err = util.ReadU64(r); err != nil { return } n += 8 @@ -227,23 +229,23 @@ func (hdr *Header) WriteTo(w io.Writer) (n int64, err error) { return } n += SignSize - if err = WriteU64(w, hdr.fttcount); err != nil { + if err = util.WriteU64(w, hdr.fttcount); err != nil { return } n += 8 - if err = WriteU64(w, hdr.fttoffset); err != nil { + if err = util.WriteU64(w, hdr.fttoffset); err != nil { return } n += 8 - if err = WriteU64(w, hdr.fttsize); err != nil { + if err = util.WriteU64(w, hdr.fttsize); err != nil { return } n += 8 - if err = WriteU64(w, hdr.datoffset); err != nil { + if err = util.WriteU64(w, hdr.datoffset); err != nil { return } n += 8 - if err = WriteU64(w, hdr.datsize); err != nil { + if err = util.WriteU64(w, hdr.datsize); err != nil { return } n += 8 @@ -255,8 +257,8 @@ const PackName = "@pack" // File tags table. type FTT struct { - info TagsetRaw // special tagset with package tags - tsm SeqMap[string, TagsetRaw] // keys - package filenames (case sensitive), values - tagset slices. + info TagsetRaw // special tagset with package tags + tsm util.SeqMap[string, TagsetRaw] // keys - package filenames (case sensitive), values - tagset slices. datoffset uint64 // files data offset datsize uint64 // files data total size @@ -358,7 +360,7 @@ func (ftt *FTT) CheckTagset(ts TagsetRaw) (fkey string, err error) { // It's high performance method without extra allocations calls. func (ftt *FTT) Parse(buf []byte) (n int64, err error) { { - var tsl = GetU16(buf[n : n+PTStssize]) + var tsl = util.GetU16(buf[n : n+PTStssize]) n += PTStssize var ts = TagsetRaw(buf[n : n+int64(tsl)]) @@ -376,7 +378,7 @@ func (ftt *FTT) Parse(buf []byte) (n int64, err error) { } for { - var tsl = GetU16(buf[n : n+PTStssize]) + var tsl = util.GetU16(buf[n : n+PTStssize]) n += PTStssize if tsl == 0 { @@ -391,7 +393,7 @@ func (ftt *FTT) Parse(buf []byte) (n int64, err error) { return } - ftt.tsm.Poke(ToSlash(fkey), ts) + ftt.tsm.Poke(util.ToSlash(fkey), ts) } return } @@ -401,7 +403,7 @@ func (ftt *FTT) ReadFrom(r io.Reader) (n int64, err error) { // read tagset with package info at first, can be empty { var tsl uint16 - if tsl, err = ReadU16(r); err != nil { + if tsl, err = util.ReadU16(r); err != nil { return } n += PTStssize @@ -425,7 +427,7 @@ func (ftt *FTT) ReadFrom(r io.Reader) (n int64, err error) { for { var tsl uint16 - if tsl, err = ReadU16(r); err != nil { + if tsl, err = util.ReadU16(r); err != nil { return } n += PTStssize @@ -445,7 +447,7 @@ func (ftt *FTT) ReadFrom(r io.Reader) (n int64, err error) { return } - ftt.tsm.Poke(ToSlash(fkey), ts) + ftt.tsm.Poke(util.ToSlash(fkey), ts) } return } @@ -461,7 +463,7 @@ func (ftt *FTT) WriteTo(w io.Writer) (n int64, err error) { } // write tagset length - if err = WriteU16(w, uint16(tsl)); err != nil { + if err = util.WriteU16(w, uint16(tsl)); err != nil { return } n += PTStssize @@ -482,7 +484,7 @@ func (ftt *FTT) WriteTo(w io.Writer) (n int64, err error) { } // write tagset length - if err = WriteU16(w, uint16(tsl)); err != nil { + if err = util.WriteU16(w, uint16(tsl)); err != nil { return false } n += PTStssize @@ -498,7 +500,7 @@ func (ftt *FTT) WriteTo(w io.Writer) (n int64, err error) { return } // write tags table end marker - if err = WriteU16(w, 0); err != nil { + if err = util.WriteU16(w, 0); err != nil { return } n += PTStssize @@ -583,7 +585,7 @@ func NewPackage() *Package { // FullPath returns concatenation of workspace and relative path. func (pkg *Package) FullPath(fkey string) string { - return JoinPath(pkg.Workspace, fkey) + return util.JoinPath(pkg.Workspace, fkey) } // TrimPath returns trimmed path without workspace prefix. @@ -610,22 +612,22 @@ func (pkg *Package) BaseTagset(offset, size uint, fkey string) TagsetRaw { return TagsetRaw{}. Put(TIDoffset, UintTag(offset)). Put(TIDsize, UintTag(size)). - Put(TIDpath, StrTag(pkg.FullPath(ToSlash(fkey)))) + Put(TIDpath, StrTag(pkg.FullPath(util.ToSlash(fkey)))) } // HasTagset check up that tagset with given filename key is present. func (pkg *Package) HasTagset(fkey string) bool { - return pkg.tsm.Has(pkg.FullPath(ToSlash(fkey))) + return pkg.tsm.Has(pkg.FullPath(util.ToSlash(fkey))) } // GetTagset returns tagset with given filename key, if it found. func (pkg *Package) GetTagset(fkey string) (TagsetRaw, bool) { - return pkg.tsm.Peek(pkg.FullPath(ToSlash(fkey))) + return pkg.tsm.Peek(pkg.FullPath(util.ToSlash(fkey))) } // SetTagset puts tagset with given filename key. func (pkg *Package) SetTagset(fkey string, ts TagsetRaw) { - pkg.tsm.Poke(pkg.FullPath(ToSlash(fkey)), ts) + pkg.tsm.Poke(pkg.FullPath(util.ToSlash(fkey)), ts) } // SetupTagset puts tagset with filename key stored at tagset. @@ -635,7 +637,7 @@ func (pkg *Package) SetupTagset(ts TagsetRaw) { // GetDelTagset deletes the tagset for a key, returning the previous tagset if any. func (pkg *Package) DelTagset(fkey string) (TagsetRaw, bool) { - return pkg.tsm.Delete(pkg.FullPath(ToSlash(fkey))) + return pkg.tsm.Delete(pkg.FullPath(util.ToSlash(fkey))) } // Enum calls given closure for each tagset in package. Skips package info. @@ -654,14 +656,14 @@ func (pkg *Package) Enum(f func(string, TagsetRaw) bool) { func (pkg *Package) Sub(dir string) (sub fs.FS, err error) { var prefix string if dir != "." && dir != "" { - prefix = ToSlash(dir) + "/" // make prefix slash-terminated + prefix = util.ToSlash(dir) + "/" // make prefix slash-terminated } pkg.Enum(func(fkey string, ts TagsetRaw) bool { if strings.HasPrefix(fkey, prefix) { sub = &Package{ FTT: pkg.FTT, Tagger: pkg.Tagger, - Workspace: pkg.FullPath(ToSlash(dir)), + Workspace: pkg.FullPath(util.ToSlash(dir)), } return false } @@ -686,7 +688,7 @@ func (pkg *Package) Stat(fkey string) (fs.FileInfo, error) { // if there is no matching file. // fs.GlobFS interface implementation. func (pkg *Package) Glob(pattern string) (res []string, err error) { - pattern = ToSlash(pattern) + pattern = util.ToSlash(pattern) if _, err = path.Match(pattern, ""); err != nil { return } @@ -763,7 +765,7 @@ func GetPackageInfo(r io.ReadSeeker) (hdr Header, ts TagsetRaw, err error) { // read first tagset that should be package info var tsl uint16 - if tsl, err = ReadU16(r); err != nil { + if tsl, err = util.ReadU16(r); err != nil { return } diff --git a/wpk_test.go b/wpk_test.go index 6db702b..7bf2bc2 100644 --- a/wpk_test.go +++ b/wpk_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/schwarzlichtbezirk/wpk" + "github.com/schwarzlichtbezirk/wpk/util" ) const mediadir = "testdata/media/" @@ -16,7 +17,7 @@ var testpkgt = wpk.TempPath("testpack.wpt") var testpkgf = wpk.TempPath("testpack.wpf") var memdata = map[string][]byte{ - "sample.txt": wpk.S2B("The quick brown fox jumps over the lazy dog"), + "sample.txt": util.S2B("The quick brown fox jumps over the lazy dog"), "array.dat": { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, @@ -182,7 +183,7 @@ func TestPackDir(t *testing.T) { return nil // file is directory } - var fpath = wpk.JoinPath(mediadir, fkey) + var fpath = util.JoinPath(mediadir, fkey) var file fs.File var ts wpk.TagsetRaw if file, err = os.Open(fpath); err != nil { @@ -304,7 +305,7 @@ func TestPackDirSplit(t *testing.T) { return nil // file is directory } - var fpath = wpk.JoinPath(mediadir, fkey) + var fpath = util.JoinPath(mediadir, fkey) var file fs.File var ts wpk.TagsetRaw if file, err = os.Open(fpath); err != nil { diff --git a/writer.go b/writer.go index 8a87cf2..25a043f 100644 --- a/writer.go +++ b/writer.go @@ -7,6 +7,8 @@ import ( "strings" "gopkg.in/djherbis/times.v1" + + "github.com/schwarzlichtbezirk/wpk/util" ) // WriteSeekCloser is typical useful interface for package writing. @@ -27,7 +29,7 @@ func (ftt *FTT) Begin(wpt, wpf io.WriteSeeker) (err error) { offset = HeaderSize } var hdr = Header{ - signature: [SignSize]byte(S2B(SignBuild)), + signature: [SignSize]byte(util.S2B(SignBuild)), fttcount: 0, fttoffset: offset, fttsize: 0, @@ -55,7 +57,7 @@ func (ftt *FTT) Append(wpt, wpf io.WriteSeeker) (err error) { return } // rewrite prebuild signature - if _, err = wpt.Write(S2B(SignBuild)); err != nil { + if _, err = wpt.Write(util.S2B(SignBuild)); err != nil { return } // go to tags table start to replace it by new data @@ -117,7 +119,7 @@ func (ftt *FTT) Sync(wpt, wpf io.WriteSeeker) (err error) { // rewrite true header var hdr = Header{ - signature: [SignSize]byte(S2B(SignReady)), + signature: [SignSize]byte(util.S2B(SignReady)), fttcount: uint64(ftt.tsm.Len()), fttoffset: uint64(fftpos), fttsize: uint64(fftend - fftpos), @@ -202,7 +204,7 @@ func (pkg *Package) Rename(fkey1, fkey2 string) error { return &fs.PathError{Op: "rename", Path: fkey2, Err: fs.ErrExist} } - ts = CopyTagset(ts).Set(TIDpath, StrTag(pkg.FullPath(ToSlash(fkey2)))) + ts = CopyTagset(ts).Set(TIDpath, StrTag(pkg.FullPath(util.ToSlash(fkey2)))) pkg.DelTagset(fkey1) pkg.SetTagset(fkey2, ts) return nil @@ -223,7 +225,7 @@ func (pkg *Package) RenameDir(olddir, newdir string, skipexist bool) (count int, err = &fs.PathError{Op: "renamedir", Path: newkey, Err: fs.ErrExist} return skipexist } - ts = CopyTagset(ts).Set(TIDpath, StrTag(pkg.FullPath(ToSlash(newkey)))) + ts = CopyTagset(ts).Set(TIDpath, StrTag(pkg.FullPath(util.ToSlash(newkey)))) pkg.DelTagset(fkey) pkg.SetTagset(newkey, ts) count++ @@ -247,7 +249,7 @@ func (pkg *Package) PutAlias(fkey1, fkey2 string) error { return &fs.PathError{Op: "putalias", Path: fkey2, Err: fs.ErrExist} } - ts = CopyTagset(ts).Set(TIDpath, StrTag(pkg.FullPath(ToSlash(fkey2)))) + ts = CopyTagset(ts).Set(TIDpath, StrTag(pkg.FullPath(util.ToSlash(fkey2)))) pkg.SetTagset(fkey2, ts) return nil }