Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/zcp-golangci-lint.yml
1 change: 1 addition & 0 deletions .github/workflows/zcp-tests.yml
83 changes: 83 additions & 0 deletions go/tools/zcp/.github/workflows/zcp-golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Format & Lint

on:
push:
paths: &paths
- "go/tools/zcp/**/*.go"
- "go/tools/zcp/go.mod"
- "go/tools/zcp/go.sum"
- "go/tools/zcp/.golangci.yml"
- "go/tools/zcp/.github/workflows/zcp-golangci-lint.yml"
- "go/tools/zcp/.github/workflows/zcp-tests.yml"
- ".github/workflows/zcp-golangci-lint.yml"
- ".github/workflows/zcp-tests.yml"
pull_request:
paths: *paths
workflow_dispatch:

concurrency:
group: zcp-format-lint-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
format:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Go with module cache
uses: actions/setup-go@v6
with:
go-version-file: go/tools/zcp/go.mod
cache: true
cache-dependency-path: |
go/tools/zcp/go.mod
go/tools/zcp/go.sum

- name: Cache golangci-lint data
uses: actions/cache@v5
with:
path: ~/.cache/golangci-lint
key: ${{ runner.os }}-golangci-format-${{ hashFiles('go/tools/zcp/go.mod', 'go/tools/zcp/go.sum', 'go/tools/zcp/.golangci.yml') }}
restore-keys: |
${{ runner.os }}-golangci-format-

- name: Check formatting via golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: latest
working-directory: go/tools/zcp
args: fmt --diff --timeout=5m ./...
skip-cache: false

lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Go with module cache
uses: actions/setup-go@v6
with:
go-version-file: go/tools/zcp/go.mod
cache: true
cache-dependency-path: |
go/tools/zcp/go.mod
go/tools/zcp/go.sum

- name: Cache golangci-lint data
uses: actions/cache@v5
with:
path: ~/.cache/golangci-lint
key: ${{ runner.os }}-golangci-${{ hashFiles('go/tools/zcp/go.mod', 'go/tools/zcp/go.sum', 'go/tools/zcp/.golangci.yml') }}
restore-keys: |
${{ runner.os }}-golangci-

- name: Run golangci-lint
uses: golangci/golangci-lint-action@v9
with:
version: latest
working-directory: go/tools/zcp
args: --timeout=5m ./...
skip-cache: false
39 changes: 39 additions & 0 deletions go/tools/zcp/.github/workflows/zcp-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Tests

on:
push:
paths: &paths
- "go/tools/zcp/**/*.go"
- "go/tools/zcp/go.mod"
- "go/tools/zcp/go.sum"
- "go/tools/zcp/.github/workflows/zcp-tests.yml"
- "go/tools/zcp/.github/workflows/zcp-golangci-lint.yml"
- ".github/workflows/zcp-tests.yml"
- ".github/workflows/zcp-golangci-lint.yml"
pull_request:
paths: *paths
workflow_dispatch:

concurrency:
group: zcp-tests-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Go with module cache
uses: actions/setup-go@v6
with:
go-version-file: go/tools/zcp/go.mod
cache: true
cache-dependency-path: |
go/tools/zcp/go.mod
go/tools/zcp/go.sum

- name: Run tests
working-directory: go/tools/zcp
run: go test ./...
20 changes: 20 additions & 0 deletions go/tools/zcp/.golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: "2"

run:
timeout: 5m
tests: true

linters:
disable-all: true
enable:
- errcheck
- govet
- ineffassign
- staticcheck
- unused

formatters:
enable:
- gofumpt
- goimports
- golines
108 changes: 108 additions & 0 deletions go/tools/zcp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# zcp

Like `cp`, but with a progress bar. The `z` is there because I liked it and to avoid name collisions.

Inspired by the original `gcp` utility:
https://manpages.ubuntu.com/manpages/focal/man1/gcp.1.html

## Features

- Copy files and directories
- Recursive directory copy (`-r`)
- Per-copy progress bar with:
- percent complete
- bytes copied / total bytes
- transfer speed
- ETA
- Optional metadata preservation (`-p` mode + mtime)
- Optional overwrite (`-f`)
- Optional verbose output (`-v`) to print created file names

## Usage

```bash
zcp [options] SOURCE... DEST
```

### Options

- `-r`, `--recursive`: copy directories recursively
- `-f`, `--force`: overwrite destination files
- `-p`, `--preserve`: preserve mode and modification time
- `-q`, `--quiet`: disable progress output
- `-v`, `--verbose`: print created file names
- `--buffer-size`: copy buffer size in bytes (default `1048576`)

### Examples

Copy a single file:

```bash
zcp movie.mkv /mnt/backup/movie.mkv
```

Copy a directory recursively:

```bash
zcp -r photos /mnt/backup/
```

Copy multiple sources into an existing destination directory:

```bash
zcp -r folder_a folder_b file.txt /mnt/backup/
```

Overwrite existing files:

```bash
zcp -f large.iso /mnt/backup/large.iso
```

Preserve source mode + mtime:

```bash
zcp -p -r assets ./assets-copy
```

Disable progress output:

```bash
zcp -q -r logs /tmp/logs-copy
```

Verbose file listing:

```bash
zcp -v -r photos /mnt/backup/
```

## Build

From this directory:

```bash
mkdir -p bin
go build -o bin/zcp ./cmd/zcp
```

### Cross-compile

Linux:

```bash
mkdir -p bin
GOOS=linux GOARCH=amd64 go build -o bin/zcp-linux-amd64 ./cmd/zcp
```

Windows:

```bash
mkdir -p bin
GOOS=windows GOARCH=amd64 go build -o bin/zcp-windows-amd64.exe ./cmd/zcp
```

## Notes

- Symbolic links are currently not copied.
- For multiple sources, destination must already exist as a directory.
Loading