Skip to content

Commit c1f73b8

Browse files
committed
feat: add merge files api
1 parent e4b462b commit c1f73b8

File tree

5 files changed

+28
-7
lines changed

5 files changed

+28
-7
lines changed

cmd/download.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@ import (
1111
type downloadOptions struct {
1212
remoteURL string
1313
out string
14+
segSize int64
15+
segCount int
1416
}
1517

1618
func newDownloadCmd(output io.Writer) *cobra.Command {
1719
var opts = &downloadOptions{}
1820

1921
var cmd = &cobra.Command{
2022
Use: "download --url [ADDRESS] --out [DIRECTORY]",
21-
Short: "download remote file and store it in the output local directory",
22-
Args: cobra.MaximumNArgs(2),
23+
Short: "download remote file and store it in a local directory",
24+
Args: cobra.MaximumNArgs(4),
2325
RunE: func(cmd *cobra.Command, args []string) error {
2426
remoteFileURL, err := url.Parse(opts.remoteURL)
2527
if err != nil {
@@ -35,8 +37,10 @@ func newDownloadCmd(output io.Writer) *cobra.Command {
3537
},
3638
}
3739

38-
cmd.Flags().StringVarP(&opts.remoteURL, "url", "u", "", "remote file address")
39-
cmd.Flags().StringVarP(&opts.out, "out", "o", "", "local directory to save file")
40+
cmd.Flags().StringVarP(&opts.remoteURL, "url", "u", "", "The remote file address to download.")
41+
cmd.Flags().StringVarP(&opts.out, "out", "o", "", "The local target directory to save file.")
42+
cmd.Flags().Int64VarP(&opts.segSize, "segment-size", "s", 0, "The size of each segment for download a file.")
43+
cmd.Flags().IntVarP(&opts.segCount, "segment-count", "n", download.DefaultNumberOfSegments, "The number of segments for download a file.")
4044

4145
return cmd
4246
}

main.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package main
22

33
import (
4-
"log"
4+
"os"
55

66
"github.com/azhovan/durable-resume/cmd"
77
)
88

99
func main() {
1010
if err := cmd.Execute(); err != nil {
11-
log.Fatalln(err)
11+
os.Exit(1)
1212
}
1313
}

pkg/download/client.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func WithHTTPClient(httpClient *http.Client) ClientOption {
4949
}
5050
}
5151

52-
// WithAuth is an option function that allow the user to provide authentication method.
52+
// WithAuth is an option function that allows the user to provide authentication method.
5353
func WithAuth(auth AuthStrategy) ClientOption {
5454
return func(client *Client) {
5555
client.auth = auth

pkg/download/dl_manager.go

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ func NewDownloadManager(downloader *Downloader, retryPolicy *RetryPolicy) *Downl
3131

3232
// Download initiates the download process.
3333
// It returns nil if the download completes successfully or an error if issues occur.
34+
// TODO(azhovan): not override existing files
3435
func (dm *DownloadManager) Download(ctx context.Context) error {
3536
err := dm.Downloader.ValidateRangeSupport(ctx, dm.Downloader.UpdateRangeSupportState)
3637
if err != nil {

pkg/download/segment.go

+16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"os"
1111
"path/filepath"
1212
"strings"
13+
"sync"
1314
"time"
1415
)
1516

@@ -265,6 +266,9 @@ func (e *SegmentError) Error() string {
265266
return fmt.Sprintf("%s, with error: %v", e.Details, e.Err)
266267
}
267268

269+
// MergeFiles concatenates multiple segment files into one file with the specified filename.
270+
// The content type of the merged file is determined by reading the first 512 bytes of the first segment.
271+
// If there are no segments to merge, it returns an ErrNoContent error.
268272
func (sm *SegmentManager) MergeFiles(filename string) error {
269273
if len(sm.Segments) == 0 {
270274
return ErrNoContent
@@ -288,6 +292,7 @@ func (sm *SegmentManager) MergeFiles(filename string) error {
288292
return err
289293
}
290294

295+
wg := &sync.WaitGroup{}
291296
// concatenate segment files
292297
for i := 1; i < len(sm.Segments); i++ {
293298
current := sm.Segments[i]
@@ -296,12 +301,23 @@ func (sm *SegmentManager) MergeFiles(filename string) error {
296301
return err
297302
}
298303

304+
wg.Add(1)
305+
299306
_, err = segment0.ReadFrom(f)
300307
if err != nil {
301308
return &SegmentError{Err: err, Details: fmt.Sprintf("reading segment %d failed", i)}
302309
}
310+
311+
// remove the temporary segment file
312+
go func(file *os.File) {
313+
defer wg.Done()
314+
_ = file.Close()
315+
_ = os.Remove(file.Name())
316+
}(f)
303317
}
304318

319+
wg.Wait()
320+
305321
err = segment0.setDone(true)
306322
if err != nil {
307323
return &SegmentError{Err: err, Details: "closing the segment 0 failed"}

0 commit comments

Comments
 (0)