cli: trim basic help, drop invented flag, parallelize by default

Surface area, not the machinery, was the problem: 16 flags crowded the
bare --help. Re-tag so basic shows only the 10 outcome-changing flags;
every other flag still works behind --help=<group>.

- cut --bt-metadata-timeout, an invented flag with no real counterpart. Keep
  its 60s magnet-metadata stall as a fixed internal default (bt.go), not a
  user knob.
- fix the parallelism footgun: a bare `got URL` used min(split,x)=1
  connection. When -x is unset, let --split drive per-host connections
  (capped at 16), so `got URL` gets 5 and `-s16` gets 16. An explicit -x
  is honored verbatim, including -x1. Locked by TestHTTPConnDefault.
- -s is the per-download speed dial now, so it moves to basic; -x (a
  per-server cap) moves to the http group. -j help says "files at once,
  not connections within one file".
This commit is contained in:
2026-06-21 15:10:57 +09:00
parent 2d99c39604
commit 3eb2d5ffcb
6 changed files with 82 additions and 55 deletions

View File

@@ -184,7 +184,6 @@ type Options struct {
SeedTime time.Duration // how long to seed (0 with SeedTimeSet means no seeding)
SeedRatio float64 // stop seeding at this ratio; checked alongside SeedTime
StopTimeout time.Duration // abort if no download progress for this long (0 = off)
MetaTimeout time.Duration // abort a magnet that can't fetch metadata in this long (0 = off)
SelectFiles map[int]bool // 1-based file indexes to fetch; empty = all
CheckIntegrity bool // re-verify data against piece hashes before downloading
DryRun bool // fetch metadata only, then stop without downloading (--dry-run)
@@ -374,27 +373,27 @@ func (d *Download) choose(t *torrent.Torrent) error {
return nil
}
// awaitInfo blocks until the torrent metadata arrives. It gives up after
// --bt-metadata-timeout (default 60s) so a magnet with no reachable peers — a
// dead link, or UDP trackers behind a firewall with no DHT — fails fast instead
// of hanging forever. Setting --bt-metadata-timeout=0 disables the timeout and
// waits indefinitely.
// metadataTimeout bounds the magnet metadata-fetch phase. A magnet with no
// reachable peers — a dead link, or UDP trackers behind a firewall with no DHT —
// would otherwise hang forever, so awaitInfo gives up after this fixed window.
// It is not a user-facing flag: aria2 has no --bt-metadata-timeout, and 60s is a
// generous ceiling that a healthy swarm clears in well under a second.
const metadataTimeout = 60 * time.Second
// awaitInfo blocks until the torrent metadata arrives, giving up after
// metadataTimeout so a peerless magnet fails fast instead of hanging forever.
func (d *Download) awaitInfo(ctx context.Context, t *torrent.Torrent) error {
var deadline <-chan time.Time
if d.opts.MetaTimeout > 0 {
tm := time.NewTimer(d.opts.MetaTimeout)
defer tm.Stop()
deadline = tm.C
}
tm := time.NewTimer(metadataTimeout)
defer tm.Stop()
select {
case <-t.GotInfo():
return nil
case <-ctx.Done():
return ctx.Err()
case <-deadline:
case <-tm.C:
// Wrap DeadlineExceeded so the exit-code mapping classifies it as a timeout
// (2) via errors.Is, rather than matching on the message text.
return fmt.Errorf("timed out fetching metadata after %s: %w", d.opts.MetaTimeout, context.DeadlineExceeded)
return fmt.Errorf("timed out fetching metadata after %s: %w", metadataTimeout, context.DeadlineExceeded)
}
}