From 834bd78bde69bdc0e4db4c1ffd7ae3d73180883f Mon Sep 17 00:00:00 2001 From: Lonny Wong Date: Sun, 26 Jun 2022 22:37:10 +0800 Subject: [PATCH] fully tested and improved --- .github/workflows/publish.yml | 37 ++++++++++++++++++ .gitignore | 3 ++ .goreleaser.yaml | 73 +++++++++++++++++++++++++++++++++++ README.md | 27 +++++++++---- debian/changelog | 8 +++- debian/control | 2 +- debian/rules | 2 +- trzsz/comm.go | 8 +++- trzsz/transfer.go | 28 +++++++------- trzsz/trzsz.go | 49 +++++++++++++++++------ trzsz/version.go | 2 +- 11 files changed, 200 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/publish.yml create mode 100644 .goreleaser.yaml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..b6aa473 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,37 @@ +name: Release and publish trzsz-go +on: + release: + types: [released] +jobs: + release-and-publish: + name: Release and publish trzsz-go + runs-on: ubuntu-latest + steps: + - name: Checkout trzsz-go + uses: actions/checkout@v3 + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: '>=1.18.0' + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v3 + with: + distribution: goreleaser + version: latest + args: release --rm-dist --skip-publish + - name: Upload Release Assets + uses: trzsz/upload-release-assets@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + release_id: ${{ github.event.release.id }} + assets_path: | + dist/*.tar.gz + dist/*.zip + - name: Publish rpm to Gemfury + env: + FURY_TOKEN: ${{ secrets.FURY_TOKEN }} + run: | + for filename in dist/trzsz*.rpm; do + curl -F package=@"$filename" https://{$FURY_TOKEN}@push.fury.io/trzsz/ + done diff --git a/.gitignore b/.gitignore index 8ae6191..d797776 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,6 @@ bin/ debian/files *.swp + +dist/ +vendor/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..efcb44d --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,73 @@ +project_name: trzsz +before: + hooks: + - go mod tidy +builds: + - id: trz + main: ./cmd/trz + binary: trz + env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + - id: tsz + main: ./cmd/tsz + binary: tsz + env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin + - id: trzsz + main: ./cmd/trzsz + binary: trzsz + env: + - CGO_ENABLED=0 + goos: + - linux + - windows + - darwin +archives: + - id: trzsz + replacements: + darwin: macos + 386: i386 + amd64: x86_64 + arm64: aarch64 + wrap_in_directory: true + format_overrides: + - goos: windows + format: zip + files: + - none* +nfpms: + - id: trzsz + builds: + - trz + - tsz + - trzsz + replacements: + amd64: 64-bit + 386: 32-bit + darwin: macOS + linux: Tux + homepage: https://trzsz.github.io/ + maintainer: Lonny Wong + description: |- + trzsz ( trz / tsz ) is a simple file transfer tools. + similar to lrzsz ( rz / sz ), and compatible with tmux. + license: MIT + formats: + - rpm + bindir: /usr/bin + overrides: + rpm: + replacements: + amd64: x86_64 + rpm: + group: Unspecified +snapshot: + name_template: '{{ .Version }}.next' diff --git a/README.md b/README.md index 7b35da1..73d5023 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ ## Installation -### on Ubuntu -*Not released yet, please download the latest [release](https://github.com/trzsz/trzsz-go/releases) from GitHub.* +### with Apt ```sh sudo add-apt-repository ppa:trzsz/ppa @@ -14,7 +13,25 @@ sudo apt install trzsz ``` -### on Windows / macOS / Other +### with Yum +``` +echo '[trzsz] +name=Trzsz Repo +baseurl=https://yum.fury.io/trzsz/ +enabled=1 +gpgcheck=0' | sudo tee /etc/yum.repos.d/trzsz.repo +sudo yum install trzsz +``` + + +### with Homebrew +``` +brew update +brew install trzsz-go +``` + + +### on Windows Please download the latest [release](https://github.com/trzsz/trzsz-go/releases) from GitHub. @@ -33,8 +50,6 @@ sudo make install ### on Local -Install the `trzsz` binary to one of the `PATH` directory. - Add `trzsz` before the shell to support trzsz ( trz / tsz ), e.g.: ```sh @@ -53,8 +68,6 @@ trzsz --dragfile ssh x.x.x.x ### on Server -Install the `trz` and `tsz` binaries to one of the `PATH` directory. - Similar to lrzsz ( rz / sz ), command `trz` to upload files, command `tsz /path/to/file` to download files. For more information, see the website of trzsz: [https://trzsz.github.io](https://trzsz.github.io/). diff --git a/debian/changelog b/debian/changelog index fd23671..3601408 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,10 @@ -trzsz (0.0.1.8) xenial; urgency=medium +trzsz (0.1.8) trusty; urgency=medium + + * Release v0.1.8 with Go1.18. + + -- Lonny Wong Sat, 25 Jun 2022 22:52:30 +0800 + +trzsz (0.0.1) xenial; urgency=medium * Initial Release. diff --git a/debian/control b/debian/control index 290bc59..ec8ca54 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: utils Priority: optional Maintainer: Lonny Wong Build-Depends: debhelper (>=9), - golang-1.13-go + golang-1.18-go Standards-Version: 3.9.6 Homepage: https://trzsz.github.io Vcs-Browser: https://github.com/trzsz/trzsz-go diff --git a/debian/rules b/debian/rules index acff9f7..ee9e9be 100755 --- a/debian/rules +++ b/debian/rules @@ -3,4 +3,4 @@ export CGO_ENABLED=0 export GOCACHE=/tmp/.cache/go-build %: - PATH="/usr/lib/go-1.13/bin:${PATH}" dh $@ + PATH="/usr/lib/go-1.18/bin:${PATH}" dh $@ diff --git a/trzsz/comm.go b/trzsz/comm.go index 40da6fd..7f38a6f 100644 --- a/trzsz/comm.go +++ b/trzsz/comm.go @@ -256,10 +256,14 @@ func checkPathReadable(pathID int, path string, info os.FileInfo, list *[]*Trzsz } for _, file := range files { p := filepath.Join(path, file.Name()) + info, err := os.Stat(p) + if err != nil { + return err + } r := make([]string, len(relPath)) copy(r, relPath) r = append(r, file.Name()) - if err := checkPathReadable(pathID, p, file, list, r, visitedDir); err != nil { + if err := checkPathReadable(pathID, p, info, list, r, visitedDir); err != nil { return err } } @@ -268,7 +272,6 @@ func checkPathReadable(pathID int, path string, info os.FileInfo, list *[]*Trzsz func checkPathsReadable(paths []string, directory bool) ([]*TrzszFile, error) { var list []*TrzszFile - visitedDir := make(map[string]bool) for i, p := range paths { path, err := filepath.Abs(p) if err != nil { @@ -283,6 +286,7 @@ func checkPathsReadable(paths []string, directory bool) ([]*TrzszFile, error) { if !directory && info.IsDir() { return nil, newTrzszError(fmt.Sprintf("Is a directory: %s", path)) } + visitedDir := make(map[string]bool) if err := checkPathReadable(i, path, info, &list, []string{info.Name()}, visitedDir); err != nil { return nil, err } diff --git a/trzsz/transfer.go b/trzsz/transfer.go index ff54470..64bb887 100644 --- a/trzsz/transfer.go +++ b/trzsz/transfer.go @@ -115,6 +115,9 @@ func (t *TrzszTransfer) cleanInput(timeoutDuration time.Duration) { } func (t *TrzszTransfer) writeAll(buf []byte) error { + if gTrzszArgs != nil && gTrzszArgs.TraceLog { + writeTraceLog(buf, false) + } written := 0 length := len(buf) for written < length { @@ -381,7 +384,6 @@ func (t *TrzszTransfer) recvConfig() (map[string]interface{}, error) { } func (t *TrzszTransfer) clientExit(msg string) error { - t.cleanInput(200 * time.Millisecond) return t.sendString("EXIT", msg) } @@ -395,9 +397,6 @@ func (t *TrzszTransfer) serverExit(msg string) { term.Restore(int(os.Stdin.Fd()), t.stdinState) } os.Stdout.WriteString("\x1b8\x1b[0J") - if IsWindows() { - os.Stdout.WriteString("\r\n") - } os.Stdout.WriteString(msg) os.Stdout.WriteString("\n") } @@ -574,22 +573,23 @@ func (t *TrzszTransfer) sendFiles(files []*TrzszFile, progress ProgressCallback) if err != nil { return nil, err } - buf := buffer[:n] - if err := t.sendData(buf, binary, escapeCodes); err != nil { + size := int64(n) + data := buffer[:n] + if err := t.sendData(data, binary, escapeCodes); err != nil { return nil, err } - if _, err := hasher.Write(buf); err != nil { + if _, err := hasher.Write(data); err != nil { return nil, err } - if err := t.checkInteger(int64(n)); err != nil { + if err := t.checkInteger(size); err != nil { return nil, err } - step += int64(n) + step += size if progress != nil && !reflect.ValueOf(progress).IsNil() { progress.onStep(step) } chunkTime := time.Now().Sub(beginTime) - if chunkTime < 500*time.Millisecond && bufSize < maxBufSize { + if size == bufSize && chunkTime < 500*time.Millisecond && bufSize < maxBufSize { bufSize = minInt64(bufSize*2, maxBufSize) buffer = make([]byte, bufSize) } @@ -624,15 +624,15 @@ func doCreateFile(path string) (*os.File, error) { file, err := os.Create(path) if err != nil { if e, ok := err.(*fs.PathError); ok { - if errno, ok := e.Err.(syscall.Errno); ok { - if errno == 13 { + if errno, ok := e.Unwrap().(syscall.Errno); ok { + if (!IsWindows() && errno == 13) || (IsWindows() && errno == 5) { return nil, newTrzszError(fmt.Sprintf("No permission to write: %s", path)) - } else if errno == 21 { + } else if (!IsWindows() && errno == 21) || (IsWindows() && errno == 0x2000002a) { return nil, newTrzszError(fmt.Sprintf("Is a directory: %s", path)) } } } - return nil, err + return nil, newTrzszError(fmt.Sprintf("%v", err)) } return file, nil } diff --git a/trzsz/trzsz.go b/trzsz/trzsz.go index a743442..c62d5e4 100644 --- a/trzsz/trzsz.go +++ b/trzsz/trzsz.go @@ -57,6 +57,7 @@ var gDragFiles []string = nil var gDragHasDir bool = false var gInterrupting bool = false var gTransfer *TrzszTransfer = nil +var gUniqueIDMap = make(map[string]int) var parentWindowID = getParentWindowID() var trzszRegexp = regexp.MustCompile("::TRZSZ:TRANSFER:([SRD]):(\\d+\\.\\d+\\.\\d+)(:\\d+)?") @@ -131,14 +132,37 @@ func getTrzszConfig(name string) *string { } func detectTrzsz(output []byte) (*byte, bool) { - if !bytes.Contains(output, []byte("::TRZSZ:TRANSFER:")) { + if len(output) < 24 { return nil, false } - match := trzszRegexp.FindSubmatch(output) + idx := bytes.LastIndex(output, []byte("::TRZSZ:TRANSFER:")) + if idx < 0 { + return nil, false + } + match := trzszRegexp.FindSubmatch(output[idx:]) if len(match) < 2 { return nil, false } - remoteIsWindows := len(match) > 3 && string(match[3]) == ":1" + uniqueID := "" + if len(match) > 3 { + uniqueID = string(match[3]) + } + if len(uniqueID) >= 8 { + if _, ok := gUniqueIDMap[uniqueID]; ok { + return nil, false + } + if len(gUniqueIDMap) > 100 { + m := make(map[string]int) + for k, v := range gUniqueIDMap { + if v >= 50 { + m[k] = v - 50 + } + } + gUniqueIDMap = m + } + gUniqueIDMap[uniqueID] = len(gUniqueIDMap) + } + remoteIsWindows := uniqueID == ":1" return &match[1][0], remoteIsWindows } @@ -345,12 +369,14 @@ func uploadDragFiles(pty *TrzszPty) { } func writeTraceLog(buf []byte, output bool) []byte { + // Windows disable log: echo ^ + // Linux macOS disable log: echo -e '\x3CDISABLE_TRZSZ_TRACE_LOG\x3E' if gTraceLog != nil { - if output && bytes.Contains(buf, []byte("\tDISABLE_TRZSZ_TRACE_LOG\t")) { + if output && bytes.Contains(buf, []byte("")) { msg := fmt.Sprintf("Closed trace log at %s", gTraceLog.Name()) gTraceLog.Close() gTraceLog = nil - return bytes.ReplaceAll(buf, []byte("\tDISABLE_TRZSZ_TRACE_LOG\t"), []byte(msg)) + return bytes.ReplaceAll(buf, []byte(""), []byte(msg)) } if output { gTraceLog.WriteString("[out]") @@ -362,7 +388,9 @@ func writeTraceLog(buf []byte, output bool) []byte { gTraceLog.Sync() return buf } - if output && bytes.Contains(buf, []byte("\tENABLE_TRZSZ_TRACE_LOG\t")) { + // Windows enable log: echo ^ + // Linux macOS enable log: echo -e '\x3CENABLE_TRZSZ_TRACE_LOG\x3E' + if output && bytes.Contains(buf, []byte("")) { var err error var msg string gTraceLog, err = os.CreateTemp("", "trzsz_*.log") @@ -371,7 +399,7 @@ func writeTraceLog(buf []byte, output bool) []byte { } else { msg = fmt.Sprintf("Writing trace log to %s", gTraceLog.Name()) } - return bytes.ReplaceAll(buf, []byte("\tENABLE_TRZSZ_TRACE_LOG\t"), []byte(msg)) + return bytes.ReplaceAll(buf, []byte(""), []byte(msg)) } return buf } @@ -508,12 +536,9 @@ func TrzszMain() int { defer func() { pty.Close() }() // set stdin in raw mode - state, err := term.MakeRaw(int(os.Stdin.Fd())) - if err != nil { - fmt.Fprintln(os.Stderr, err) - return -2 + if state, err := term.MakeRaw(int(os.Stdin.Fd())); err == nil { + defer func() { _ = term.Restore(int(os.Stdin.Fd()), state) }() } - defer func() { _ = term.Restore(int(os.Stdin.Fd()), state) }() // wrap input and output go wrapInput(pty) diff --git a/trzsz/version.go b/trzsz/version.go index d78b48c..46475f3 100644 --- a/trzsz/version.go +++ b/trzsz/version.go @@ -24,4 +24,4 @@ SOFTWARE. package trzsz -const kTrzszVersion = "0.1.7" +const kTrzszVersion = "0.1.8"