diff --git a/hw07_file_copying/.sync b/hw07_file_copying/.sync deleted file mode 100644 index e69de29..0000000 diff --git a/hw07_file_copying/copy.go b/hw07_file_copying/copy.go index 1ddf87b..0d76a77 100644 --- a/hw07_file_copying/copy.go +++ b/hw07_file_copying/copy.go @@ -2,14 +2,70 @@ package main import ( "errors" + "fmt" + "github.com/cheggaaa/pb" + "io" + "os" ) var ( - ErrUnsupportedFile = errors.New("unsupported file") + // ErrUnsupportedFile = errors.New("unsupported file") ErrOffsetExceedsFileSize = errors.New("offset exceeds file size") + ErrTheSameFile = errors.New("you are trying to rewrite the source file") ) func Copy(fromPath, toPath string, offset, limit int64) error { - // Place your code here. + if fromPath == toPath { + return ErrTheSameFile + } + + inFile, err := os.Open(fromPath) + if err != nil { + return fmt.Errorf("open input file: %w", err) + } + + defer inFile.Close() + + fileStat, err := os.Stat(fromPath) + if err != nil { + return fmt.Errorf("read input file info: %w", err) + } + + fileSize := fileStat.Size() + if fileSize < offset { + return ErrOffsetExceedsFileSize + } + + if limit == 0 { + limit = fileSize + } + + if limit > fileSize-offset { + limit = fileSize - offset + } + + outFile, err := os.Create(toPath) + if err != nil { + return fmt.Errorf("open output file: %w", err) + } + + defer outFile.Close() + + if offset > 0 { + inFile.Seek(offset, io.SeekStart) + } + + bar := pb.StartNew(int(limit)) + bar.Start() + + reader := bar.NewProxyReader(inFile) + + _, err = io.CopyN(outFile, reader, limit) + if err != nil { + return fmt.Errorf("copy data to file: %w", err) + } + + bar.Finish() + return nil } diff --git a/hw07_file_copying/copy_test.go b/hw07_file_copying/copy_test.go index e070942..4da7542 100644 --- a/hw07_file_copying/copy_test.go +++ b/hw07_file_copying/copy_test.go @@ -1,7 +1,59 @@ package main -import "testing" +import ( + "crypto/md5" + "fmt" + "github.com/stretchr/testify/require" + "io" + "os" + "testing" +) + +func FileMD5(path string) string { + h := md5.New() + f, err := os.Open(path) + if err != nil { + panic(err) + } + defer f.Close() + _, err = io.Copy(h, f) + if err != nil { + panic(err) + } + return fmt.Sprintf("%x", h.Sum(nil)) +} func TestCopy(t *testing.T) { - // Place your code here. + err := Copy("testdata/file_does_not_exist.txt", "/tmp/copy_offset0_limit0.txt", 0, 0) + require.Error(t, err) + + err = Copy("testdata/input.txt", "testdata/input.txt", 0, 0) + require.Error(t, err) + + err = Copy("testdata/input.txt", "/tmp/offset_is_bigger_then_file_size.txt", 100000, 0) + require.Error(t, err) + + err = Copy("testdata/input.txt", "/tmp/copy_offset0_limit0.txt", 0, 0) + require.NoError(t, err) + require.Equal(t, FileMD5("testdata/out_offset0_limit0.txt"), FileMD5("/tmp/copy_offset0_limit0.txt")) + + err = Copy("testdata/input.txt", "/tmp/copy_offset0_limit10.txt", 0, 10) + require.NoError(t, err) + require.Equal(t, FileMD5("testdata/out_offset0_limit10.txt"), FileMD5("/tmp/copy_offset0_limit10.txt")) + + err = Copy("testdata/input.txt", "/tmp/copy_offset0_limit1000.txt", 0, 1000) + require.NoError(t, err) + require.Equal(t, FileMD5("testdata/out_offset0_limit1000.txt"), FileMD5("/tmp/copy_offset0_limit1000.txt")) + + err = Copy("testdata/input.txt", "/tmp/copy_offset0_limit10000.txt", 0, 10000) + require.NoError(t, err) + require.Equal(t, FileMD5("testdata/out_offset0_limit10000.txt"), FileMD5("/tmp/copy_offset0_limit10000.txt")) + + err = Copy("testdata/input.txt", "/tmp/copy_offset100_limit1000.txt", 100, 1000) + require.NoError(t, err) + require.Equal(t, FileMD5("testdata/out_offset100_limit1000.txt"), FileMD5("/tmp/copy_offset100_limit1000.txt")) + + err = Copy("testdata/input.txt", "/tmp/copy_offset6000_limit1000.txt", 6000, 1000) + require.NoError(t, err) + require.Equal(t, FileMD5("testdata/out_offset6000_limit1000.txt"), FileMD5("/tmp/copy_offset6000_limit1000.txt")) } diff --git a/hw07_file_copying/go.mod b/hw07_file_copying/go.mod index 65868f7..30b8dc0 100644 --- a/hw07_file_copying/go.mod +++ b/hw07_file_copying/go.mod @@ -1,3 +1,12 @@ -module github.com/fixme_my_friend/hw07_file_copying +module github.com/sofiiakulish/hw07_file_copying go 1.16 + +require ( + github.com/cheggaaa/pb v1.0.29 + github.com/fatih/color v1.10.0 // indirect + github.com/mattn/go-runewidth v0.0.12 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + github.com/stretchr/testify v1.8.0 + golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect +) diff --git a/hw07_file_copying/go.sum b/hw07_file_copying/go.sum index e69de29..0cd8a44 100644 --- a/hw07_file_copying/go.sum +++ b/hw07_file_copying/go.sum @@ -0,0 +1,39 @@ +github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo= +github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxmAOow= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/hw07_file_copying/hw07_file_copying b/hw07_file_copying/hw07_file_copying new file mode 100755 index 0000000..3ac9686 Binary files /dev/null and b/hw07_file_copying/hw07_file_copying differ diff --git a/hw07_file_copying/main.go b/hw07_file_copying/main.go index 515e844..603fa5d 100644 --- a/hw07_file_copying/main.go +++ b/hw07_file_copying/main.go @@ -18,5 +18,5 @@ func init() { func main() { flag.Parse() - // Place your code here. + Copy(from, to, offset, limit) }