diff options
author | Wim <wim@42.be> | 2022-01-31 00:27:37 +0100 |
---|---|---|
committer | Wim <wim@42.be> | 2022-03-20 14:57:48 +0100 |
commit | e3cafeaf9292f67459ff1d186f68283bfaedf2ae (patch) | |
tree | b69c39620aa91dba695b3b935c6651c0fb37ce75 /vendor/modernc.org/ccgo/v3/lib/util.go | |
parent | e7b193788a56ee7cdb02a87a9db0ad6724ef66d5 (diff) | |
download | matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.tar.gz matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.tar.bz2 matterbridge-msglm-e3cafeaf9292f67459ff1d186f68283bfaedf2ae.zip |
Add dependencies/vendor (whatsapp)
Diffstat (limited to 'vendor/modernc.org/ccgo/v3/lib/util.go')
-rw-r--r-- | vendor/modernc.org/ccgo/v3/lib/util.go | 458 |
1 files changed, 458 insertions, 0 deletions
diff --git a/vendor/modernc.org/ccgo/v3/lib/util.go b/vendor/modernc.org/ccgo/v3/lib/util.go new file mode 100644 index 00000000..f11e439c --- /dev/null +++ b/vendor/modernc.org/ccgo/v3/lib/util.go @@ -0,0 +1,458 @@ +// Copyright 2020 The CCGO Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// generator.go helpers + +package ccgo // import "modernc.org/ccgo/v3/lib" + +import ( + "archive/tar" + "bufio" + "bytes" + "compress/gzip" + "fmt" + "io" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "runtime/debug" + "strings" +) + +// CopyFile copies src to dest, preserving permissions and times where/when +// possible. If canOverwrite is not nil, it is consulted whether a destination +// file can be overwritten. If canOverwrite is nil then destination is +// overwritten if permissions allow that, otherwise the function fails. +// +// Src and dst must be in the slash form. +func CopyFile(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) (n int64, rerr error) { + dst = filepath.FromSlash(dst) + dstDir := filepath.Dir(dst) + di, err := os.Stat(dstDir) + switch { + case err != nil: + if !os.IsNotExist(err) { + return 0, err + } + + if err := os.MkdirAll(dstDir, 0770); err != nil { + return 0, err + } + case err == nil: + if !di.IsDir() { + return 0, fmt.Errorf("cannot create directory, file exists: %s", dst) + } + } + + src = filepath.FromSlash(src) + si, err := os.Stat(src) + if err != nil { + return 0, err + } + + if si.IsDir() { + return 0, fmt.Errorf("cannot copy a directory: %s", src) + } + + di, err = os.Stat(dst) + switch { + case err != nil && !os.IsNotExist(err): + return 0, err + case err == nil: + if di.IsDir() { + return 0, fmt.Errorf("cannot overwite a directory: %s", dst) + } + + if canOverwrite != nil && !canOverwrite(dst, di) { + return 0, fmt.Errorf("cannot overwite: %s", dst) + } + } + + s, err := os.Open(src) + if err != nil { + return 0, err + } + + defer s.Close() + r := bufio.NewReader(s) + + d, err := os.Create(dst) + + defer func() { + if err := d.Close(); err != nil && rerr == nil { + rerr = err + return + } + + if err := os.Chmod(dst, si.Mode()); err != nil && rerr == nil { + rerr = err + return + } + + if err := os.Chtimes(dst, si.ModTime(), si.ModTime()); err != nil && rerr == nil { + rerr = err + return + } + }() + + w := bufio.NewWriter(d) + + defer func() { + if err := w.Flush(); err != nil && rerr == nil { + rerr = err + } + }() + + return io.Copy(w, r) +} + +// MustCopyFile is like CopyFile but it executes Fatal(stackTrace, err) if it fails. +func MustCopyFile(stackTrace bool, dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) int64 { + n, err := CopyFile(dst, src, canOverwrite) + if err != nil { + Fatal(stackTrace, err) + } + + return n +} + +// CopyDir recursively copies src to dest, preserving permissions and times +// where/when possible. If canOverwrite is not nil, it is consulted whether a +// destination file can be overwritten. If canOverwrite is nil then destination +// is overwritten if permissions allow that, otherwise the function fails. +// +// Src and dst must be in the slash form. +func CopyDir(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) (files int, bytes int64, rerr error) { + dst = filepath.FromSlash(dst) + src = filepath.FromSlash(src) + si, err := os.Stat(src) + if err != nil { + return 0, 0, err + } + + if !si.IsDir() { + return 0, 0, fmt.Errorf("cannot copy a file: %s", src) + } + + return files, bytes, filepath.Walk(src, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + rel, err := filepath.Rel(src, path) + if err != nil { + return err + } + + if info.IsDir() { + return os.MkdirAll(filepath.Join(dst, rel), 0770) + } + + n, err := CopyFile(filepath.Join(dst, rel), path, canOverwrite) + if err != nil { + return err + } + + files++ + bytes += n + return nil + }) +} + +// MustCopyDir is like CopyDir, but it executes Fatal(stackTrace, errĂº if it fails. +func MustCopyDir(stackTrace bool, dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) (files int, bytes int64) { + file, bytes, err := CopyDir(dst, src, canOverwrite) + if err != nil { + Fatal(stackTrace, err) + } + + return file, bytes +} + +// UntarFile extracts a named tar.gz archive into dst. If canOverwrite is not +// nil, it is consulted whether a destination file can be overwritten. If +// canOverwrite is nil then destination is overwritten if permissions allow +// that, otherwise the function fails. +// +// Src and dst must be in the slash form. +func UntarFile(dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) error { + f, err := os.Open(filepath.FromSlash(src)) + if err != nil { + return err + } + + defer f.Close() + + return Untar(dst, bufio.NewReader(f), canOverwrite) +} + +// MustUntarFile is like UntarFile but it executes Fatal(stackTrace, err) if it fails. +func MustUntarFile(stackTrace bool, dst, src string, canOverwrite func(fn string, fi os.FileInfo) bool) { + if err := UntarFile(dst, src, canOverwrite); err != nil { + Fatal(stackTrace, err) + } +} + +// Untar extracts a tar.gz archive into dst. If canOverwrite is not nil, it is +// consulted whether a destination file can be overwritten. If canOverwrite is +// nil then destination is overwritten if permissions allow that, otherwise the +// function fails. +// +// Dst must be in the slash form. +func Untar(dst string, r io.Reader, canOverwrite func(fn string, fi os.FileInfo) bool) error { + dst = filepath.FromSlash(dst) + gr, err := gzip.NewReader(r) + if err != nil { + return err + } + + tr := tar.NewReader(gr) + for { + hdr, err := tr.Next() + if err != nil { + if err != io.EOF { + return err + } + + return nil + } + + switch hdr.Typeflag { + case tar.TypeDir: + dir := filepath.Join(dst, hdr.Name) + if err = os.MkdirAll(dir, 0770); err != nil { + return err + } + case tar.TypeSymlink, tar.TypeXGlobalHeader: + // skip + case tar.TypeReg, tar.TypeRegA: + dir := filepath.Dir(filepath.Join(dst, hdr.Name)) + if _, err := os.Stat(dir); err != nil { + if !os.IsNotExist(err) { + return err + } + + if err = os.MkdirAll(dir, 0770); err != nil { + return err + } + } + + fn := filepath.Join(dst, hdr.Name) + f, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY, os.FileMode(hdr.Mode)) + if err != nil { + return err + } + + w := bufio.NewWriter(f) + if _, err = io.Copy(w, tr); err != nil { + return err + } + + if err := w.Flush(); err != nil { + return err + } + + if err := f.Close(); err != nil { + return err + } + + if err := os.Chtimes(fn, hdr.AccessTime, hdr.ModTime); err != nil { + return err + } + default: + return fmt.Errorf("unexpected tar header typeflag %#02x", hdr.Typeflag) + } + } + +} + +// MustUntar is like Untar but it executes Fatal(stackTrace, err) if it fails. +func MustUntar(stackTrace bool, dst string, r io.Reader, canOverwrite func(fn string, fi os.FileInfo) bool) { + if err := Untar(dst, r, canOverwrite); err != nil { + Fatal(stackTrace, err) + } +} + +// Fatalf prints a formatted message to os.Stderr and performs os.Exit(1). A +// stack trace is added if stackTrace is true. +func Fatalf(stackTrace bool, s string, args ...interface{}) { + if stackTrace { + fmt.Fprintf(os.Stderr, "%s\n", debug.Stack()) + } + fmt.Fprintln(os.Stderr, strings.TrimSpace(fmt.Sprintf(s, args...))) + os.Exit(1) +} + +// Fatal prints its argumenst to os.Stderr and performs os.Exit(1). A +// stack trace is added if stackTrace is true. +func Fatal(stackTrace bool, args ...interface{}) { + if stackTrace { + fmt.Fprintf(os.Stderr, "%s\n", debug.Stack()) + } + fmt.Fprintln(os.Stderr, strings.TrimSpace(fmt.Sprint(args...))) + os.Exit(1) +} + +// Mkdirs will create all paths. Paths must be in slash form. +func Mkdirs(paths ...string) error { + for _, path := range paths { + path = filepath.FromSlash(path) + if err := os.MkdirAll(path, 0770); err != nil { + return err + } + } + + return nil +} + +// MustMkdirs is like Mkdir but if executes Fatal(stackTrace, err) if it fails. +func MustMkdirs(stackTrace bool, paths ...string) { + if err := Mkdirs(paths...); err != nil { + Fatal(stackTrace, err) + } +} + +// InDir executes f in dir. Dir must be in slash form. +func InDir(dir string, f func() error) (err error) { + var cwd string + if cwd, err = os.Getwd(); err != nil { + return err + } + + defer func() { + if err2 := os.Chdir(cwd); err2 != nil { + err = err2 + } + }() + + if err = os.Chdir(filepath.FromSlash(dir)); err != nil { + return err + } + + return f() +} + +// MustInDir is like InDir but it executes Fatal(stackTrace, err) if it fails. +func MustInDir(stackTrace bool, dir string, f func() error) { + if err := InDir(dir, f); err != nil { + Fatal(stackTrace, err) + } +} + +type echoWriter struct { + w bytes.Buffer +} + +func (w *echoWriter) Write(b []byte) (int, error) { + os.Stdout.Write(b) + return w.w.Write(b) +} + +// Shell echoes and executes cmd with args and returns the combined output if the command. +func Shell(cmd string, args ...string) ([]byte, error) { + cmd, err := exec.LookPath(cmd) + if err != nil { + return nil, err + } + + wd, err := AbsCwd() + if err != nil { + return nil, err + } + + fmt.Printf("execute %s %q in %s\n", cmd, args, wd) + var b echoWriter + c := exec.Command(cmd, args...) + c.Stdout = &b + c.Stderr = &b + err = c.Run() + return b.w.Bytes(), err +} + +// MustShell is like Shell but it executes Fatal(stackTrace, err) if it fails. +func MustShell(stackTrace bool, cmd string, args ...string) []byte { + b, err := Shell(cmd, args...) + if err != nil { + Fatalf(stackTrace, "%v %s\noutput: %s\nerr: %s", cmd, args, b, err) + } + + return b +} + +// Compile executes Shell with cmd set to "ccgo". +func Compile(args ...string) ([]byte, error) { return Shell("ccgo", args...) } + +// MustCompile is like Compile but if executes Fatal(stackTrace, err) if it fails. +func MustCompile(stackTrace bool, args ...string) []byte { + return MustShell(stackTrace, "ccgo", args...) +} + +// Run is like Compile, but executes in-process. +func Run(args ...string) ([]byte, error) { + var b bytes.Buffer + t := NewTask(append([]string{"ccgo"}, args...), &b, &b) + err := t.Main() + return b.Bytes(), err +} + +// MustRun is like Run but if executes Fatal(stackTrace, err) if it fails. +func MustRun(stackTrace bool, args ...string) []byte { + var b bytes.Buffer + args = append([]string{"ccgo"}, args...) + t := NewTask(args, &b, &b) + if err := t.Main(); err != nil { + Fatalf(stackTrace, "%v\noutput: %s\nerr: %s", args, b.Bytes(), err) + } + + return b.Bytes() +} + +// AbsCwd returns the absolute working directory. +func AbsCwd() (string, error) { + wd, err := os.Getwd() + if err != nil { + return "", err + } + + if wd, err = filepath.Abs(wd); err != nil { + return "", err + } + + return wd, nil +} + +// MustAbsCwd is like AbsCwd but executes Fatal(stackTrace, err) if it fails. +func MustAbsCwd(stackTrace bool) string { + s, err := AbsCwd() + if err != nil { + Fatal(stackTrace, err) + } + + return s +} + +// Env returns the value of environmental variable key of dflt otherwise. +func Env(key, dflt string) string { + if s := os.Getenv(key); s != "" { + return s + } + + return dflt +} + +// MustTempDir is like ioutil.TempDir but executes Fatal(stackTrace, err) if it +// fails. The returned path is absolute. +func MustTempDir(stackTrace bool, dir, name string) string { + s, err := ioutil.TempDir(dir, name) + if err != nil { + Fatal(stackTrace, err) + } + + if s, err = filepath.Abs(s); err != nil { + Fatal(stackTrace, err) + } + + return s +} |