Skip to content

Commit 7642731

Browse files
committed
Merge branch 'main' of github.com:autobrr/mkbrr
2 parents e234434 + 88c2f04 commit 7642731

File tree

11 files changed

+68
-75
lines changed

11 files changed

+68
-75
lines changed

README.md

+4-6
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,21 @@ version: 1
9696
jobs:
9797
- output: ubuntu.torrent
9898
path: /path/to/ubuntu.iso
99-
name: "Ubuntu 22.04 LTS"
10099
trackers:
101-
- udp://tracker.opentrackr.org:1337/announce
100+
- https://tracker.openbittorrent.com/announce
102101
webseeds:
103102
- https://releases.ubuntu.com/22.04/ubuntu-22.04.3-desktop-amd64.iso
104-
piece_length: 20 # 1MB pieces (2^20)
105103
comment: "Ubuntu 22.04.3 LTS Desktop AMD64"
106104
private: false
107105

108106
- output: release.torrent
109107
path: /path/to/release
110-
name: "My Release"
111108
trackers:
112-
- udp://tracker.example.com:1337/announce
113-
piece_length: 18 # 256KB pieces (2^18)
109+
- https://tracker.openbittorrent.com/announce
114110
private: true
115111
source: "GROUP"
112+
comment: "My awesome release"
113+
no_date: false
116114
```
117115
118116
Batch mode will process all jobs in parallel (up to 4 concurrent jobs) and provide a summary of results.

cmd/create.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ func init() {
7171
}
7272

7373
createCmd.Flags().StringVarP(&outputPath, "output", "o", "", "set output path (default: <n>.torrent)")
74-
createCmd.Flags().StringVarP(&torrentName, "name", "n", "", "set torrent name (default: basename of target)")
7574
createCmd.Flags().StringVarP(&source, "source", "s", "", "add source string")
7675
createCmd.Flags().BoolVarP(&noDate, "no-date", "d", false, "don't write creation date")
7776
createCmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "be verbose")
@@ -95,7 +94,7 @@ func runCreate(cmd *cobra.Command, args []string) error {
9594

9695
start := time.Now()
9796

98-
// Batch mode
97+
// batch mode
9998
if batchFile != "" {
10099
results, err := torrent.ProcessBatch(batchFile, verbose, version)
101100
if err != nil {
@@ -107,7 +106,7 @@ func runCreate(cmd *cobra.Command, args []string) error {
107106
return nil
108107
}
109108

110-
// Single file mode
109+
// single file mode
111110
if _, err := os.Stat(args[0]); err != nil {
112111
return fmt.Errorf("invalid path %q: %w", args[0], err)
113112
}

examples/batch.yaml

+11-18
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,21 @@
22
version: 1
33
jobs:
44
# Single file torrent
5-
- output: ubuntu.torrent
6-
path: /path/to/ubuntu.iso
7-
name: "Ubuntu 22.04 LTS"
5+
- output: random_movie.torrent
6+
path: /Users/user/Downloads/Random.Movie.Title.2023.1080p.WEB-DL.mkv
87
trackers:
9-
- udp://tracker.opentrackr.org:1337/announce
10-
- udp://tracker.openbittorrent.com:6969/announce
11-
webseeds:
12-
- https://releases.ubuntu.com/22.04/ubuntu-22.04.3-desktop-amd64.iso
13-
piece_length: 20 # 1MB pieces (2^20)
14-
comment: "Ubuntu 22.04.3 LTS Desktop AMD64"
8+
- https://tracker.randomtracker.org/announce
9+
#piece_length: 20
10+
comment: "Random Movie Title - A thrilling adventure"
1511
private: false
1612

1713
# Directory torrent
18-
- output: release.torrent
19-
path: /path/to/release
20-
name: "My Release"
14+
- output: random_release.torrent
15+
path: '/Users/user/Downloads/Random Album - Best Hits (2025)'
2116
trackers:
22-
- udp://tracker.example.com:1337/announce
23-
webseeds:
24-
- https://cdn.example.com/release/
25-
piece_length: 18 # 256KB pieces (2^18)
17+
- https://tracker.anothertracker.com/announce
18+
#piece_length: 18
2619
private: true
27-
source: "GROUP"
28-
comment: "My awesome release"
20+
source: "MUSIC"
21+
comment: "Best Hits Compilation - 2025 Edition"
2922
no_date: false

internal/torrent/batch.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ type BatchConfig struct {
1919
type BatchJob struct {
2020
Output string `yaml:"output"`
2121
Path string `yaml:"path"`
22-
Name string `yaml:"name"`
22+
Name string `yaml:"-"`
2323
Trackers []string `yaml:"trackers"`
2424
WebSeeds []string `yaml:"webseeds"`
2525
Private bool `yaml:"private"`
@@ -95,7 +95,7 @@ func ProcessBatch(configPath string, verbose bool, version string) ([]BatchResul
9595
return nil, fmt.Errorf("no jobs defined in batch config")
9696
}
9797

98-
// Validate all jobs before processing
98+
// validate all jobs before processing
9999
for _, job := range config.Jobs {
100100
if err := validateJob(job); err != nil {
101101
return nil, fmt.Errorf("invalid job configuration: %w", err)
@@ -105,11 +105,11 @@ func ProcessBatch(configPath string, verbose bool, version string) ([]BatchResul
105105
results := make([]BatchResult, len(config.Jobs))
106106
var wg sync.WaitGroup
107107

108-
// Process jobs in parallel with a worker pool
109-
workers := minInt(len(config.Jobs), 4) // Limit concurrent jobs
108+
// process jobs in parallel with a worker pool
109+
workers := minInt(len(config.Jobs), 4) // limit concurrent jobs
110110
jobs := make(chan int, len(config.Jobs))
111111

112-
// Start workers
112+
// start workers
113113
for i := 0; i < workers; i++ {
114114
wg.Add(1)
115115
go func() {
@@ -120,7 +120,7 @@ func ProcessBatch(configPath string, verbose bool, version string) ([]BatchResul
120120
}()
121121
}
122122

123-
// Send jobs to workers
123+
// send jobs to workers
124124
for i := range config.Jobs {
125125
jobs <- i
126126
}
@@ -156,23 +156,23 @@ func processJob(job BatchJob, verbose bool, version string) BatchResult {
156156
Trackers: job.Trackers,
157157
}
158158

159-
// Ensure output has .torrent extension
159+
// ensure output has .torrent extension
160160
output := job.Output
161161
if filepath.Ext(output) != ".torrent" {
162162
output += ".torrent"
163163
}
164164

165-
// Convert job to CreateTorrentOptions
165+
// convert job to CreateTorrentOptions
166166
opts := job.ToCreateOptions(verbose, version)
167167

168-
// Create the torrent
168+
// create the torrent
169169
mi, err := CreateTorrent(opts)
170170
if err != nil {
171171
result.Error = fmt.Errorf("failed to create torrent: %w", err)
172172
return result
173173
}
174174

175-
// Write the torrent file
175+
// write the torrent file
176176
f, err := os.Create(output)
177177
if err != nil {
178178
result.Error = fmt.Errorf("failed to create output file: %w", err)
@@ -185,7 +185,7 @@ func processJob(job BatchJob, verbose bool, version string) BatchResult {
185185
return result
186186
}
187187

188-
// Collect torrent info
188+
// collect torrent info
189189
info := mi.GetInfo()
190190
result.Success = true
191191
result.Info = &TorrentInfo{

internal/torrent/batch_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import (
88
)
99

1010
func TestProcessBatch(t *testing.T) {
11-
// Create a temporary directory for test files
11+
// create a temporary directory for test files
1212
tmpDir, err := os.MkdirTemp("", "mkbrr-batch-test")
1313
if err != nil {
1414
t.Fatalf("Failed to create temp dir: %v", err)
1515
}
1616
defer os.RemoveAll(tmpDir)
1717

18-
// Create test files and directories
18+
// create test files and directories
1919
testFiles := []struct {
2020
path string
2121
content string
@@ -44,7 +44,7 @@ func TestProcessBatch(t *testing.T) {
4444
}
4545
}
4646

47-
// Create batch config file
47+
// create batch config file
4848
configPath := filepath.Join(tmpDir, "batch.yaml")
4949
configContent := []byte(fmt.Sprintf(`version: 1
5050
jobs:
@@ -73,13 +73,13 @@ jobs:
7373
t.Fatalf("Failed to write config file: %v", err)
7474
}
7575

76-
// Process batch
76+
// process batch
7777
results, err := ProcessBatch(configPath, true, "test-version")
7878
if err != nil {
7979
t.Fatalf("ProcessBatch failed: %v", err)
8080
}
8181

82-
// Verify results
82+
// verify results
8383
if len(results) != 2 {
8484
t.Errorf("Expected 2 results, got %d", len(results))
8585
}
@@ -95,12 +95,12 @@ jobs:
9595
continue
9696
}
9797

98-
// Verify torrent files were created
98+
// verify torrent files were created
9999
if _, err := os.Stat(result.Info.Path); err != nil {
100100
t.Errorf("Job %d torrent file not created: %v", i, err)
101101
}
102102

103-
// Basic validation of torrent info
103+
// basic validation of torrent info
104104
if result.Info.InfoHash == "" {
105105
t.Errorf("Job %d missing info hash", i)
106106
}
@@ -109,7 +109,7 @@ jobs:
109109
t.Errorf("Job %d has zero size", i)
110110
}
111111

112-
// Check specific job details
112+
// check specific job details
113113
switch i {
114114
case 0: // file1.txt
115115
if result.Info.Files != 0 {

internal/torrent/create.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,14 @@ func CreateTorrent(opts CreateTorrentOptions) (*Torrent, error) {
147147
}
148148

149149
if len(files) == 1 {
150-
// Check if the input path is a directory
150+
// check if the input path is a directory
151151
pathInfo, err := os.Stat(path)
152152
if err != nil {
153153
return nil, fmt.Errorf("error checking path: %w", err)
154154
}
155155

156156
if pathInfo.IsDir() {
157-
// If it's a directory, use the folder structure even for single files
157+
// if it's a directory, use the folder structure even for single files
158158
info.Files = make([]metainfo.FileInfo, 1)
159159
relPath, _ := filepath.Rel(baseDir, files[0].path)
160160
pathComponents := strings.Split(relPath, string(filepath.Separator))
@@ -163,7 +163,7 @@ func CreateTorrent(opts CreateTorrentOptions) (*Torrent, error) {
163163
Length: files[0].length,
164164
}
165165
} else {
166-
// If it's a single file directly, use the simple format
166+
// if it's a single file directly, use the simple format
167167
info.Length = files[0].length
168168
}
169169
} else {

internal/torrent/display.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,17 @@ func (d *Display) ShowFileTree(info *metainfo.Info) {
144144
}
145145

146146
func (d *Display) ShowOutputPathWithTime(path string, duration time.Duration) {
147-
fmt.Printf("\n%s %s (%s)\n",
148-
success("Wrote"),
149-
white(path),
150-
cyan("took "+d.formatter.FormatDuration(duration)))
147+
if duration < time.Second {
148+
fmt.Printf("\n%s %s (%s)\n",
149+
success("Wrote"),
150+
white(path),
151+
cyan(fmt.Sprintf("elapsed %dms", duration.Milliseconds())))
152+
} else {
153+
fmt.Printf("\n%s %s (%s)\n",
154+
success("Wrote"),
155+
white(path),
156+
cyan(fmt.Sprintf("elapsed %.2fs", duration.Seconds())))
157+
}
151158
}
152159

153160
func (d *Display) ShowBatchResults(results []BatchResult, duration time.Duration) {

internal/torrent/hasher.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ type pieceHasher struct {
2727
// - single vs multiple files
2828
// - average file size
2929
// - system CPU count
30-
// Returns readSize (buffer size for reading) and numWorkers (concurrent goroutines)
30+
// returns readSize (buffer size for reading) and numWorkers (concurrent goroutines)
3131
func (h *pieceHasher) optimizeForWorkload() (int, int) {
3232
if len(h.files) == 0 {
3333
return 0, 0
@@ -91,7 +91,7 @@ func (h *pieceHasher) hashPieces(numWorkers int) error {
9191
h.readSize, numWorkers = h.optimizeForWorkload()
9292

9393
if numWorkers == 0 {
94-
// No workers needed, possibly no pieces to hash
94+
// no workers needed, possibly no pieces to hash
9595
h.display.ShowProgress(0)
9696
h.display.FinishProgress()
9797
return nil

internal/torrent/hasher_large_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func TestPieceHasher_LargeFiles(t *testing.T) {
5151
files, expectedHashes := createTestFilesFast(t, tt.numFiles, tt.fileSize, tt.pieceLen)
5252
hasher := NewPieceHasher(files, tt.pieceLen, tt.numPieces, &mockDisplay{})
5353

54-
// Test with different worker counts
54+
// test with different worker counts
5555
workerCounts := []int{1, 2, 4, 8}
5656
for _, workers := range workerCounts {
5757
t.Run(fmt.Sprintf("workers_%d", workers), func(t *testing.T) {

0 commit comments

Comments
 (0)