You've already forked docker-volume-backup
mirror of
https://github.com/offen/docker-volume-backup.git
synced 2025-11-29 05:46:50 +02:00
Update golangci integration (#637)
* Update golangci integration * Fix newly discovered errcheck complaints * Increase timeout value
This commit is contained in:
41
.github/workflows/golangci-lint.yml
vendored
41
.github/workflows/golangci-lint.yml
vendored
@@ -7,7 +7,6 @@ on:
|
|||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
# Optional: allow read access to pull request. Use with `only-new-issues` option.
|
|
||||||
pull-requests: read
|
pull-requests: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -15,40 +14,12 @@ jobs:
|
|||||||
name: lint
|
name: lint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v5
|
||||||
- uses: actions/setup-go@v5
|
- uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version: '1.24'
|
go-version: '1.25'
|
||||||
cache: false
|
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v6
|
uses: golangci/golangci-lint-action@v8
|
||||||
with:
|
with:
|
||||||
# Require: The version of golangci-lint to use.
|
version: v2.4
|
||||||
# When `install-mode` is `binary` (default) the value can be v1.2 or v1.2.3 or `latest` to use the latest version.
|
args: --timeout 5m
|
||||||
# When `install-mode` is `goinstall` the value can be v1.2.3, `latest`, or the hash of a commit.
|
|
||||||
version: v1.64
|
|
||||||
|
|
||||||
# Optional: working directory, useful for monorepos
|
|
||||||
# working-directory: somedir
|
|
||||||
|
|
||||||
# Optional: golangci-lint command line arguments.
|
|
||||||
#
|
|
||||||
# Note: By default, the `.golangci.yml` file should be at the root of the repository.
|
|
||||||
# The location of the configuration file can be changed by using `--config=`
|
|
||||||
# args: --timeout=30m --config=/my/path/.golangci.yml --issues-exit-code=0
|
|
||||||
|
|
||||||
# Optional: show only new issues if it's a pull request. The default value is `false`.
|
|
||||||
# only-new-issues: true
|
|
||||||
|
|
||||||
# Optional: if set to true, then all caching functionality will be completely disabled,
|
|
||||||
# takes precedence over all other caching options.
|
|
||||||
# skip-cache: true
|
|
||||||
|
|
||||||
# Optional: if set to true, then the action won't cache or restore ~/go/pkg.
|
|
||||||
# skip-pkg-cache: true
|
|
||||||
|
|
||||||
# Optional: if set to true, then the action won't cache or restore ~/.cache/go-build.
|
|
||||||
# skip-build-cache: true
|
|
||||||
|
|
||||||
# Optional: The mode to install golangci-lint. It can be 'binary' or 'goinstall'.
|
|
||||||
# install-mode: "goinstall"
|
|
||||||
|
|||||||
2
.github/workflows/unit.yml
vendored
2
.github/workflows/unit.yml
vendored
@@ -14,7 +14,7 @@ jobs:
|
|||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v4
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: '1.24.x'
|
go-version: '1.25.x'
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: go mod download
|
run: go mod download
|
||||||
- name: Test with the Go CLI
|
- name: Test with the Go CLI
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
|
version: '2'
|
||||||
linters:
|
linters:
|
||||||
# Enable specific linter
|
# Enable specific linter
|
||||||
# https://golangci-lint.run/usage/linters/#enabled-by-default
|
# https://golangci-lint.run/usage/linters/#enabled-by-default
|
||||||
enable:
|
enable:
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- govet
|
- govet
|
||||||
output:
|
|
||||||
formats:
|
|
||||||
- format: colored-line-number
|
|
||||||
|
|||||||
@@ -121,10 +121,11 @@ func getCompressionWriter(file *os.File, algo string, concurrency int) (io.Write
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeTarball(path string, tarWriter *tar.Writer, prefix string) error {
|
func writeTarball(path string, tarWriter *tar.Writer, prefix string) (returnErr error) {
|
||||||
fileInfo, err := os.Lstat(path)
|
fileInfo, err := os.Lstat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, fmt.Sprintf("error getting file info for %s", path))
|
returnErr = errwrap.Wrap(err, fmt.Sprintf("error getting file info for %s", path))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileInfo.Mode()&os.ModeSocket == os.ModeSocket {
|
if fileInfo.Mode()&os.ModeSocket == os.ModeSocket {
|
||||||
@@ -135,19 +136,22 @@ func writeTarball(path string, tarWriter *tar.Writer, prefix string) error {
|
|||||||
if fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
|
if fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||||
var err error
|
var err error
|
||||||
if link, err = os.Readlink(path); err != nil {
|
if link, err = os.Readlink(path); err != nil {
|
||||||
return errwrap.Wrap(err, fmt.Sprintf("error resolving symlink %s", path))
|
returnErr = errwrap.Wrap(err, fmt.Sprintf("error resolving symlink %s", path))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
header, err := tar.FileInfoHeader(fileInfo, link)
|
header, err := tar.FileInfoHeader(fileInfo, link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, "error getting file info header")
|
returnErr = errwrap.Wrap(err, "error getting file info header")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
header.Name = strings.TrimPrefix(path, prefix)
|
header.Name = strings.TrimPrefix(path, prefix)
|
||||||
|
|
||||||
err = tarWriter.WriteHeader(header)
|
err = tarWriter.WriteHeader(header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, "error writing file info header")
|
returnErr = errwrap.Wrap(err, "error writing file info header")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !fileInfo.Mode().IsRegular() {
|
if !fileInfo.Mode().IsRegular() {
|
||||||
@@ -156,13 +160,17 @@ func writeTarball(path string, tarWriter *tar.Writer, prefix string) error {
|
|||||||
|
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, fmt.Sprintf("error opening %s", path))
|
returnErr = errwrap.Wrap(err, fmt.Sprintf("error opening %s", path))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer func() {
|
||||||
|
returnErr = file.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
_, err = io.Copy(tarWriter, file)
|
_, err = io.Copy(tarWriter, file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, fmt.Sprintf("error copying %s to tar writer", path))
|
returnErr = errwrap.Wrap(err, fmt.Sprintf("error copying %s to tar writer", path))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -153,13 +153,13 @@ func source(path string) (map[string]string, error) {
|
|||||||
currentValue, currentOk := os.LookupEnv(key)
|
currentValue, currentOk := os.LookupEnv(key)
|
||||||
defer func() {
|
defer func() {
|
||||||
if currentOk {
|
if currentOk {
|
||||||
os.Setenv(key, currentValue)
|
_ = os.Setenv(key, currentValue)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
os.Unsetenv(key)
|
_ = os.Unsetenv(key)
|
||||||
}()
|
}()
|
||||||
result[key] = value
|
result[key] = value
|
||||||
os.Setenv(key, value)
|
_ = os.Setenv(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|||||||
@@ -60,8 +60,10 @@ func TestSource(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Setenv("QUX", "yyy")
|
_ = os.Setenv("QUX", "yyy")
|
||||||
defer os.Unsetenv("QUX")
|
defer func() {
|
||||||
|
_ = os.Unsetenv("QUX")
|
||||||
|
}()
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
|||||||
@@ -177,8 +177,12 @@ func (s *script) runLabeledCommands(label string) error {
|
|||||||
s.logger.Info(fmt.Sprintf("Running %s command %s for container %s", label, cmd, strings.TrimPrefix(c.Names[0], "/")))
|
s.logger.Info(fmt.Sprintf("Running %s command %s for container %s", label, cmd, strings.TrimPrefix(c.Names[0], "/")))
|
||||||
stdout, stderr, err := s.exec(c.ID, cmd, user)
|
stdout, stderr, err := s.exec(c.ID, cmd, user)
|
||||||
if s.c.ExecForwardOutput {
|
if s.c.ExecForwardOutput {
|
||||||
os.Stderr.Write(stderr)
|
if _, err := os.Stderr.Write(stderr); err != nil {
|
||||||
os.Stdout.Write(stdout)
|
return errwrap.Wrap(err, "error writing to stderr")
|
||||||
|
}
|
||||||
|
if _, err := os.Stdout.Write(stdout); err != nil {
|
||||||
|
return errwrap.Wrap(err, "error writing to stdout")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, "error executing command")
|
return errwrap.Wrap(err, "error executing command")
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/cli/cli/command/service/progress"
|
"github.com/docker/cli/cli/command/service/progress"
|
||||||
"github.com/docker/docker/api/types/container"
|
|
||||||
ctr "github.com/docker/docker/api/types/container"
|
ctr "github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
@@ -66,7 +65,7 @@ func awaitContainerCountForService(cli *client.Client, serviceID string, count i
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
case <-poll.C:
|
case <-poll.C:
|
||||||
containers, err := cli.ContainerList(context.Background(), container.ListOptions{
|
containers, err := cli.ContainerList(context.Background(), ctr.ListOptions{
|
||||||
Filters: filters.NewArgs(filters.KeyValuePair{
|
Filters: filters.NewArgs(filters.KeyValuePair{
|
||||||
Key: "label",
|
Key: "label",
|
||||||
Value: fmt.Sprintf("com.docker.swarm.service.id=%s", serviceID),
|
Value: fmt.Sprintf("com.docker.swarm.service.id=%s", serviceID),
|
||||||
@@ -124,11 +123,11 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
|||||||
labelValue,
|
labelValue,
|
||||||
)
|
)
|
||||||
|
|
||||||
allContainers, err := s.cli.ContainerList(context.Background(), container.ListOptions{})
|
allContainers, err := s.cli.ContainerList(context.Background(), ctr.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return noop, errwrap.Wrap(err, "error querying for containers")
|
return noop, errwrap.Wrap(err, "error querying for containers")
|
||||||
}
|
}
|
||||||
containersToStop, err := s.cli.ContainerList(context.Background(), container.ListOptions{
|
containersToStop, err := s.cli.ContainerList(context.Background(), ctr.ListOptions{
|
||||||
Filters: filters.NewArgs(filters.KeyValuePair{
|
Filters: filters.NewArgs(filters.KeyValuePair{
|
||||||
Key: "label",
|
Key: "label",
|
||||||
Value: filterMatchLabel,
|
Value: filterMatchLabel,
|
||||||
@@ -215,7 +214,7 @@ func (s *script) stopContainersAndServices() (func() error, error) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
var stoppedContainers []container.Summary
|
var stoppedContainers []ctr.Summary
|
||||||
var stopErrors []error
|
var stopErrors []error
|
||||||
for _, container := range containersToStop {
|
for _, container := range containersToStop {
|
||||||
if err := s.cli.ContainerStop(context.Background(), container.ID, ctr.StopOptions{}); err != nil {
|
if err := s.cli.ContainerStop(context.Background(), container.ID, ctr.StopOptions{}); err != nil {
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module github.com/offen/docker-volume-backup
|
module github.com/offen/docker-volume-backup
|
||||||
|
|
||||||
go 1.24.0
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
filippo.io/age v1.2.1
|
filippo.io/age v1.2.1
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ func (b *dropboxStorage) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy copies the given file to the WebDav storage backend.
|
// Copy copies the given file to the WebDav storage backend.
|
||||||
func (b *dropboxStorage) Copy(file string) error {
|
func (b *dropboxStorage) Copy(file string) (returnErr error) {
|
||||||
_, name := path.Split(file)
|
_, name := path.Split(file)
|
||||||
|
|
||||||
folderArg := files.NewCreateFolderArg(b.DestinationPath)
|
folderArg := files.NewCreateFolderArg(b.DestinationPath)
|
||||||
@@ -95,19 +95,24 @@ func (b *dropboxStorage) Copy(file string) error {
|
|||||||
switch err := err.(type) {
|
switch err := err.(type) {
|
||||||
case files.CreateFolderV2APIError:
|
case files.CreateFolderV2APIError:
|
||||||
if err.EndpointError.Path.Tag != files.WriteErrorConflict {
|
if err.EndpointError.Path.Tag != files.WriteErrorConflict {
|
||||||
return errwrap.Wrap(err, fmt.Sprintf("error creating directory '%s'", b.DestinationPath))
|
returnErr = errwrap.Wrap(err, fmt.Sprintf("error creating directory '%s'", b.DestinationPath))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
b.Log(storage.LogLevelInfo, b.Name(), "Destination path '%s' already exists, no new directory required.", b.DestinationPath)
|
b.Log(storage.LogLevelInfo, b.Name(), "Destination path '%s' already exists, no new directory required.", b.DestinationPath)
|
||||||
default:
|
default:
|
||||||
return errwrap.Wrap(err, fmt.Sprintf("error creating directory '%s'", b.DestinationPath))
|
returnErr = errwrap.Wrap(err, fmt.Sprintf("error creating directory '%s'", b.DestinationPath))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := os.Open(file)
|
r, err := os.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, "error opening the file to be uploaded")
|
returnErr = errwrap.Wrap(err, "error opening the file to be uploaded")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer r.Close()
|
defer func() {
|
||||||
|
returnErr = r.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
// Start new upload session and get session id
|
// Start new upload session and get session id
|
||||||
b.Log(storage.LogLevelInfo, b.Name(), "Starting upload session for backup '%s' at path '%s'.", file, b.DestinationPath)
|
b.Log(storage.LogLevelInfo, b.Name(), "Starting upload session for backup '%s' at path '%s'.", file, b.DestinationPath)
|
||||||
@@ -116,7 +121,8 @@ func (b *dropboxStorage) Copy(file string) error {
|
|||||||
uploadSessionStartArg := files.NewUploadSessionStartArg()
|
uploadSessionStartArg := files.NewUploadSessionStartArg()
|
||||||
uploadSessionStartArg.SessionType = &files.UploadSessionType{Tagged: dropbox.Tagged{Tag: files.UploadSessionTypeConcurrent}}
|
uploadSessionStartArg.SessionType = &files.UploadSessionType{Tagged: dropbox.Tagged{Tag: files.UploadSessionTypeConcurrent}}
|
||||||
if res, err := b.client.UploadSessionStart(uploadSessionStartArg, nil); err != nil {
|
if res, err := b.client.UploadSessionStart(uploadSessionStartArg, nil); err != nil {
|
||||||
return errwrap.Wrap(err, "error starting the upload session")
|
returnErr = errwrap.Wrap(err, "error starting the upload session")
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
sessionId = res.SessionId
|
sessionId = res.SessionId
|
||||||
}
|
}
|
||||||
@@ -197,7 +203,8 @@ loop:
|
|||||||
files.NewCommitInfo(path.Join(b.DestinationPath, name)),
|
files.NewCommitInfo(path.Join(b.DestinationPath, name)),
|
||||||
), nil)
|
), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, "error finishing the upload session")
|
returnErr = errwrap.Wrap(err, "error finishing the upload session")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Log(storage.LogLevelInfo, b.Name(), "Uploaded a copy of backup '%s' at path '%s'.", file, b.DestinationPath)
|
b.Log(storage.LogLevelInfo, b.Name(), "Uploaded a copy of backup '%s' at path '%s'.", file, b.DestinationPath)
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"crypto/tls"
|
||||||
"github.com/offen/docker-volume-backup/internal/errwrap"
|
"github.com/offen/docker-volume-backup/internal/errwrap"
|
||||||
"github.com/offen/docker-volume-backup/internal/storage"
|
"github.com/offen/docker-volume-backup/internal/storage"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
"golang.org/x/oauth2/google"
|
"golang.org/x/oauth2/google"
|
||||||
"google.golang.org/api/drive/v3"
|
"google.golang.org/api/drive/v3"
|
||||||
"google.golang.org/api/option"
|
"google.golang.org/api/option"
|
||||||
"golang.org/x/oauth2"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"crypto/tls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type googleDriveStorage struct {
|
type googleDriveStorage struct {
|
||||||
@@ -84,15 +84,18 @@ func (b *googleDriveStorage) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy copies the given file to the Google Drive storage backend.
|
// Copy copies the given file to the Google Drive storage backend.
|
||||||
func (b *googleDriveStorage) Copy(file string) error {
|
func (b *googleDriveStorage) Copy(file string) (returnErr error) {
|
||||||
_, name := filepath.Split(file)
|
_, name := filepath.Split(file)
|
||||||
b.Log(storage.LogLevelInfo, b.Name(), "Starting upload for backup '%s'.", name)
|
b.Log(storage.LogLevelInfo, b.Name(), "Starting upload for backup '%s'.", name)
|
||||||
|
|
||||||
f, err := os.Open(file)
|
f, err := os.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, fmt.Sprintf("failed to open file %s", file))
|
returnErr = errwrap.Wrap(err, fmt.Sprintf("failed to open file %s", file))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer func() {
|
||||||
|
returnErr = f.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
driveFile := &drive.File{Name: name}
|
driveFile := &drive.File{Name: name}
|
||||||
if b.DestinationPath != "" {
|
if b.DestinationPath != "" {
|
||||||
@@ -104,7 +107,8 @@ func (b *googleDriveStorage) Copy(file string) error {
|
|||||||
createCall := b.client.Files.Create(driveFile).SupportsAllDrives(true).Fields("id")
|
createCall := b.client.Files.Create(driveFile).SupportsAllDrives(true).Fields("id")
|
||||||
created, err := createCall.Media(f).Do()
|
created, err := createCall.Media(f).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, fmt.Sprintf("failed to upload %s", name))
|
returnErr = errwrap.Wrap(err, fmt.Sprintf("failed to upload %s", name))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Log(storage.LogLevelInfo, b.Name(), "Finished upload for %s. File ID: %s", name, created.Id)
|
b.Log(storage.LogLevelInfo, b.Name(), "Finished upload for %s. File ID: %s", name, created.Id)
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ func (b *localStorage) Copy(file string) error {
|
|||||||
if b.latestSymlink != "" {
|
if b.latestSymlink != "" {
|
||||||
symlink := path.Join(b.DestinationPath, b.latestSymlink)
|
symlink := path.Join(b.DestinationPath, b.latestSymlink)
|
||||||
if _, err := os.Lstat(symlink); err == nil {
|
if _, err := os.Lstat(symlink); err == nil {
|
||||||
os.Remove(symlink)
|
if err := os.Remove(symlink); err != nil {
|
||||||
|
return errwrap.Wrap(err, "error removing existing symlink")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err := os.Symlink(name, symlink); err != nil {
|
if err := os.Symlink(name, symlink); err != nil {
|
||||||
return errwrap.Wrap(err, "error creating latest symlink")
|
return errwrap.Wrap(err, "error creating latest symlink")
|
||||||
@@ -146,22 +148,25 @@ func (b *localStorage) Prune(deadline time.Time, pruningPrefix string) (*storage
|
|||||||
}
|
}
|
||||||
|
|
||||||
// copy creates a copy of the file located at `dst` at `src`.
|
// copy creates a copy of the file located at `dst` at `src`.
|
||||||
func copyFile(src, dst string) error {
|
func copyFile(src, dst string) (returnErr error) {
|
||||||
in, err := os.Open(src)
|
in, err := os.Open(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
returnErr = err
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer in.Close()
|
defer func() {
|
||||||
|
returnErr = in.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
out, err := os.Create(dst)
|
out, err := os.Create(dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
returnErr = err
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = io.Copy(out, in)
|
_, err = io.Copy(out, in)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
out.Close()
|
return errors.Join(err, out.Close())
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
return out.Close()
|
return out.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,19 +106,25 @@ func (b *sshStorage) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy copies the given file to the SSH storage backend.
|
// Copy copies the given file to the SSH storage backend.
|
||||||
func (b *sshStorage) Copy(file string) error {
|
func (b *sshStorage) Copy(file string) (returnErr error) {
|
||||||
source, err := os.Open(file)
|
source, err := os.Open(file)
|
||||||
_, name := path.Split(file)
|
_, name := path.Split(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, " error reading the file to be uploaded")
|
returnErr = errwrap.Wrap(err, " error reading the file to be uploaded")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer source.Close()
|
defer func() {
|
||||||
|
returnErr = source.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
destination, err := b.sftpClient.Create(path.Join(b.DestinationPath, name))
|
destination, err := b.sftpClient.Create(path.Join(b.DestinationPath, name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, "error creating file")
|
returnErr = errwrap.Wrap(err, "error creating file")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer destination.Close()
|
defer func() {
|
||||||
|
returnErr = destination.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
chunk := make([]byte, 1e9)
|
chunk := make([]byte, 1e9)
|
||||||
for {
|
for {
|
||||||
@@ -126,27 +132,32 @@ func (b *sshStorage) Copy(file string) error {
|
|||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
tot, err := destination.Write(chunk[:num])
|
tot, err := destination.Write(chunk[:num])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, "error uploading the file")
|
returnErr = errwrap.Wrap(err, "error uploading the file")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if tot != len(chunk[:num]) {
|
if tot != len(chunk[:num]) {
|
||||||
return errwrap.Wrap(nil, "failed to write stream")
|
returnErr = errwrap.Wrap(nil, "failed to write stream")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, "error uploading the file")
|
returnErr = errwrap.Wrap(err, "error uploading the file")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tot, err := destination.Write(chunk[:num])
|
tot, err := destination.Write(chunk[:num])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errwrap.Wrap(err, "error uploading the file")
|
returnErr = errwrap.Wrap(err, "error uploading the file")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if tot != len(chunk[:num]) {
|
if tot != len(chunk[:num]) {
|
||||||
return errwrap.Wrap(nil, "failed to write stream")
|
returnErr = errwrap.Wrap(nil, "failed to write stream")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user