From adfcb26a4660bb89ba90eb0b7db1a8b99c500c7f Mon Sep 17 00:00:00 2001 From: xhd2015 Date: Tue, 22 Oct 2024 14:30:03 +0800 Subject: [PATCH] add script/vendir --- CONTRIBUTING.md | 3 +- cmd/xgo/version.go | 4 +- support/edit/LICENSE | 27 ++++++++++ support/edit/edit.go | 99 +++++++++++++++++++++++++++++++++++ support/edit/goedit/goedit.go | 42 +++++++++++++++ support/filecopy/copy.go | 37 ++++++++++--- support/goinfo/find.go | 3 ++ support/goinfo/mod.go | 34 +++++++++--- 8 files changed, 233 insertions(+), 16 deletions(-) create mode 100644 support/edit/LICENSE create mode 100644 support/edit/edit.go create mode 100644 support/edit/goedit/goedit.go diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 899af9e9..54ae2493 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -128,8 +128,9 @@ Here is a guide on how to make a new release: - run `git commit -m "release v1.0.49"`, this will run git hooks that updates `REVISION` and `NUMBER`, and copies `CORE_VERSION`,`CORE_REVISION`,`CORE_NUMBER` to [runtime/core/version.go](runtime/core/version.go) so that if a runtime is running with an older xgo, it will print warnings. - run `git tag v1.0.49`, if there is runtime update, run `git tag runtime/v1.0.49`. - run `git push --tags`. +- ask maintainer to push to master - go to github release page to draft a new release - run `go run ./script/build-release`, run this in a standalone worktree if necessary. - upload built binaries. - update release notes. -- release. \ No newline at end of file +- release. diff --git a/cmd/xgo/version.go b/cmd/xgo/version.go index 09ffca1a..23488f6d 100644 --- a/cmd/xgo/version.go +++ b/cmd/xgo/version.go @@ -6,8 +6,8 @@ import "fmt" // VERSION is manually updated when needed a new tag // see also runtime/core/version.go const VERSION = "1.0.50" -const REVISION = "403a999217b51a86240a37e57c09ddfc6a731851+1" -const NUMBER = 315 +const REVISION = "8996d11f4f17ea3f1d67de6dacecccac5a49d549+1" +const NUMBER = 316 // the matching runtime/core's version // manually updated diff --git a/support/edit/LICENSE b/support/edit/LICENSE new file mode 100644 index 00000000..54ce0710 --- /dev/null +++ b/support/edit/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/support/edit/edit.go b/support/edit/edit.go new file mode 100644 index 00000000..7810e2e0 --- /dev/null +++ b/support/edit/edit.go @@ -0,0 +1,99 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package edit implements buffered position-based editing of byte slices. +package edit + +import ( + "fmt" + "sort" +) + +// A Buffer is a queue of edits to apply to a given byte slice. +type Buffer struct { + old []byte + q edits +} + +// An edit records a single text modification: change the bytes in [start,end) to new. +type edit struct { + start int + end int + new string +} + +// An edits is a list of edits that is sortable by start offset, breaking ties by end offset. +type edits []edit + +func (x edits) Len() int { return len(x) } +func (x edits) Swap(i, j int) { x[i], x[j] = x[j], x[i] } +func (x edits) Less(i, j int) bool { + if x[i].start != x[j].start { + return x[i].start < x[j].start + } + return x[i].end < x[j].end +} + +// NewBuffer returns a new buffer to accumulate changes to an initial data slice. +// The returned buffer maintains a reference to the data, so the caller must ensure +// the data is not modified until after the Buffer is done being used. +func NewBuffer(data []byte) *Buffer { + return &Buffer{old: data} +} + +func (b *Buffer) Insert(pos int, new string) { + if pos < 0 || pos > len(b.old) { + panic("invalid edit position") + } + b.q = append(b.q, edit{pos, pos, new}) +} + +func (b *Buffer) Delete(start, end int) { + if end == -1 { + end = len(b.old) + } + if end < start || start < 0 || end > len(b.old) { + panic("invalid edit position") + } + b.q = append(b.q, edit{start, end, ""}) +} + +func (b *Buffer) Replace(start, end int, new string) { + if end == -1 { + end = len(b.old) + } + if end < start || start < 0 || end > len(b.old) { + panic("invalid edit position") + } + b.q = append(b.q, edit{start, end, new}) +} + +// Bytes returns a new byte slice containing the original data +// with the queued edits applied. +func (b *Buffer) Bytes() []byte { + // Sort edits by starting position and then by ending position. + // Breaking ties by ending position allows insertions at point x + // to be applied before a replacement of the text at [x, y). + sort.Stable(b.q) + + var new []byte + offset := 0 + for i, e := range b.q { + if e.start < offset { + e0 := b.q[i-1] + panic(fmt.Sprintf("overlapping edits: [%d,%d)->%q, [%d,%d)->%q", e0.start, e0.end, e0.new, e.start, e.end, e.new)) + } + new = append(new, b.old[offset:e.start]...) + offset = e.end + new = append(new, e.new...) + } + new = append(new, b.old[offset:]...) + return new +} + +// String returns a string containing the original data +// with the queued edits applied. +func (b *Buffer) String() string { + return string(b.Bytes()) +} diff --git a/support/edit/goedit/goedit.go b/support/edit/goedit/goedit.go new file mode 100644 index 00000000..75919369 --- /dev/null +++ b/support/edit/goedit/goedit.go @@ -0,0 +1,42 @@ +package goedit + +import ( + "go/token" + + "github.com/xhd2015/xgo/support/edit" +) + +type Edit struct { + buf *edit.Buffer + fset *token.FileSet +} + +func New(fset *token.FileSet, content string) *Edit { + return &Edit{ + fset: fset, + buf: edit.NewBuffer([]byte(content)), + } +} + +func (c *Edit) Delete(start token.Pos, end token.Pos) { + c.buf.Delete(c.offsetOf(start), c.offsetOf(end)) +} + +func (c *Edit) Insert(start token.Pos, content string) { + c.buf.Insert(c.offsetOf(start), content) +} + +func (c *Edit) Replace(start token.Pos, end token.Pos, content string) { + c.buf.Replace(c.offsetOf(start), c.offsetOf(end), content) +} + +func (c *Edit) String() string { + return c.buf.String() +} + +func (c *Edit) offsetOf(pos token.Pos) int { + if pos == token.NoPos { + return -1 + } + return c.fset.Position(pos).Offset +} diff --git a/support/filecopy/copy.go b/support/filecopy/copy.go index bda9f58b..84f12d51 100644 --- a/support/filecopy/copy.go +++ b/support/filecopy/copy.go @@ -18,6 +18,8 @@ type Options struct { ignoreSubPaths []string ignoreSuffix []string includeSuffix []string + + noRm bool } func NewOptions() *Options { @@ -48,23 +50,42 @@ func (c *Options) IncludeSuffix(suffix ...string) *Options { return c } +func (c *Options) Copy(srcDir string, targetDir string) error { + var cloneOpts *Options + if c == nil { + cloneOpts = &Options{noRm: true} + } else { + clone := *c + cloneOpts = &clone + cloneOpts.noRm = true + } + return copyReplaceDir(srcDir, targetDir, cloneOpts) +} + func (c *Options) CopyReplaceDir(srcDir string, targetDir string) error { return copyReplaceDir(srcDir, targetDir, c) } +func Copy(srcDir string, targetDir string) error { + return copyReplaceDir(srcDir, targetDir, &Options{ + noRm: true, + }) +} + // Replace the target dir with files copy func CopyReplaceDir(srcDir string, targetDir string, useLink bool) error { return copyReplaceDir(srcDir, targetDir, &Options{ useLink: useLink, }) } + func copyReplaceDir(srcDir string, targetDir string, opts *Options) error { - if opts == nil { - opts = &Options{} - } if srcDir == "" { return fmt.Errorf("requires srcDir") } + if opts == nil { + opts = &Options{} + } var filterSubPath func(subPath string, isDir bool) bool if opts != nil && (len(opts.includeSuffix) > 0 || len(opts.ignoreSubPaths) > 0 || len(opts.ignoreSuffix) > 0) { @@ -116,9 +137,12 @@ func copyReplaceDir(srcDir string, targetDir string, opts *Options) error { if parent == targetAbsDir { return fmt.Errorf("unable to override %v", targetDir) } - err = os.RemoveAll(targetAbsDir) - if err != nil { - return err + if !opts.noRm { + // remove target + err = os.RemoveAll(targetAbsDir) + if err != nil { + return err + } } err = os.MkdirAll(filepath.Dir(targetAbsDir), 0755) @@ -281,6 +305,7 @@ func CopyFile(src string, dst string) error { return copyFile(src, dst, false, nil) } +// CopyFileAll copy src to dst, creates dir if necessary func CopyFileAll(src string, dst string) error { return copyFile(src, dst, true, nil) } diff --git a/support/goinfo/find.go b/support/goinfo/find.go index c05108f1..ada35238 100644 --- a/support/goinfo/find.go +++ b/support/goinfo/find.go @@ -15,6 +15,9 @@ func FindGoModDir(dir string) (string, error) { return dir, err } +// FindGoModDirSubPath find go.mod by traversing dir bottom up, +// upon finding a go.mod file, it returns the corresponding +// sub path and root dir func FindGoModDirSubPath(dir string) ([]string, string, error) { absDir, err := filepath.Abs(dir) if err != nil { diff --git a/support/goinfo/mod.go b/support/goinfo/mod.go index 0346bc6e..1433c8e7 100644 --- a/support/goinfo/mod.go +++ b/support/goinfo/mod.go @@ -30,6 +30,17 @@ func ResolveMainModule(dir string) (subPaths []string, mainModule string, err er return subPaths, modPath, nil } +func ResolveModulePkgPath(dir string) (mainModPath string, pkgPath string, err error) { + subPaths, mainModule, err := ResolveMainModule(dir) + if err != nil { + return "", "", err + } + if len(subPaths) == 0 { + return mainModule, mainModule, nil + } + return mainModule, mainModule + "/" + strings.Join(subPaths, "/"), nil +} + func isRelative(arg string) bool { if arg == "" { // pwd @@ -60,20 +71,22 @@ func findGoMod(dir string) (file string, subPaths []string, err error) { return "", nil, err } iterDir := absDir + var nextIterDir string init := true for { if init { init = false } else { subPaths = append(subPaths, filepath.Base(iterDir)) - nextIterDir := filepath.Dir(iterDir) - if iterDir == string(filepath.Separator) || nextIterDir == iterDir { - // until root - // TODO: what about windows? - return "", nil, ErrGoModNotFound - } iterDir = nextIterDir } + nextIterDir = filepath.Dir(iterDir) + if iterDir == string(filepath.Separator) || nextIterDir == iterDir { + // until root + // TODO: what about windows? + return "", nil, ErrGoModNotFound + } + file := filepath.Join(iterDir, "go.mod") stat, err := os.Stat(file) if err != nil { @@ -86,8 +99,15 @@ func findGoMod(dir string) (file string, subPaths []string, err error) { continue } // a valid go.mod found - return file, subPaths, nil + return file, reverse(subPaths), nil + } +} +func reverse(list []string) []string { + n := len(list) + for i, j := 0, n-1; i < j; i, j = i+1, j-1 { + list[i], list[j] = list[j], list[i] } + return list } func parseModPath(goModContent string) string {