syncer: warn that SSH stats and progress are incomplete · Entire
syncer: warn that SSH stats and progress are incomplete
9aa3e87→main ·
Soph·2mo ago·2 files·+87 added/-2 removed
Sessions
1ae05f312d98 View transcript
Changes
2
internal/syncer
Msyncer.go +37/-1
Msyncer_test.go +50/-1
535 unmodified lines
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
83 unmodified lines
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
5 unmodified lines
671
672
673
674
675
676
677
10 unmodified lines
688
689
690
691
692
693
694
22 unmodified lines
717
718
719
683
720
721
722
535 unmodified lines
return false
}
func sshStatsWarning(cfg Config, sourceConn, targetConn gitproto.Conn) string {
if !cfg.Progress && !cfg.ShowStats {
return ""
}
hasSSH := false
if _, ok := sourceConn.(*gitproto.SSHConn); ok {
hasSSH = true
}
if !hasSSH && targetConn != nil {
if _, ok := targetConn.(*gitproto.SSHConn); ok {
hasSSH = true
}
}
if !hasSSH {
return ""
}
return "warning: SSH transport does not yet expose byte-counted throughput; --progress and --show-stats output will omit SSH transfer bytes"
}
// --- Session setup (issue #12) ---
// syncSession holds the shared state for a sync operation, reducing
83 unmodified lines
stats: newStats(cfg.ShowStats),
measurementDone: startMeasurement(cfg.MeasureMemory),
}
var warnedSSHStats bool
warnSSHStats := func(sourceConn, targetConn gitproto.Conn) {
if warnedSSHStats {
return
}
warning := sshStatsWarning(cfg, sourceConn, targetConn)
if warning == "" {
return
}
warnedSSHStats = true
out := cfg.progressOut
if out == nil {
out = os.Stderr
}
fmt.Fprintln(out, warning)
}
if cfg.Verbose {
s.logger = slog.New(slog.NewTextHandler(&sessionStderr{s: s}, &slog.HandlerOptions{
Level: slog.LevelInfo,
5 unmodified lines
return nil, fmt.Errorf("create source transport: %w", err)
}
s.sourceConn.SetProgressWriter(&sessionStderr{s: s})
warnSSHStats(s.sourceConn, nil)
refPrefixes := planner.RefPrefixes(planConfig(cfg))
sourceRefs, sourceService, err := gitproto.ListSourceRefs(ctx, s.sourceConn, cfg.ProtocolMode, refPrefixes)
10 unmodified lines
return nil, fmt.Errorf("create target transport: %w", err)
}
targetConn.SetProgressWriter(&sessionStderr{s: s})
warnSSHStats(s.sourceConn, targetConn)
targetAdv, err := gitproto.AdvertisedRefsV1(ctx, targetConn, transport.ReceivePackService)
if err != nil {
return nil, fmt.Errorf("list target refs: %w", err)
}
22 unmodified lines
}
}
}
// Start the live progress ticker only after auth resolution and the
// initial ref-listing round trips have completed. The auth path may
// shell out to `git credential fill`, which inherits our stderr and
Minternal/syncer/syncer.go +37/-1
1 unmodified line
2
3
4
5
6
7
8
9
236 unmodified lines
246
247
248
249
250
251
252
253
248
254
255
256
257
14 unmodified lines
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
1 unmodified line
import (
"context"
"os"
"path/filepath"
"strings"
"testing"
236 unmodified lines
func TestNewConnBuildsSSHTransport(t *testing.T) {
orig := gitproto.SSHLookPath
t.Cleanup(func() { gitproto.SSHLookPath = orig })
script := filepath.Join(t.TempDir(), "ssh-stub.sh")
if err := os.WriteFile(script, []byte("#!/bin/sh\nexit 1\n"), 0o755); err != nil {
t.Fatalf("write ssh stub: %v", err)
}
gitproto.SSHLookPath = func(string) (string, error) {
return "/usr/bin/ssh", nil
return script, nil
}
stats := newStats(false)
14 unmodified lines
})
}
}
func TestSSHStatsWarning(t *testing.T) {
tests := []struct {
name string
cfg Config
source gitproto.Conn
target gitproto.Conn
want bool
}{
{
name: "no flags",
cfg: Config{},
source: &gitproto.SSHConn{},
},
{
name: "http only",
cfg: Config{Progress: true},
source: &gitproto.HTTPConn{},
target: &gitproto.HTTPConn{},
},
{
name: "progress with ssh source",
cfg: Config{Progress: true},
source: &gitproto.SSHConn{},
want: true,
},
{
name: "show stats with ssh target",
cfg: Config{ShowStats: true},
source: &gitproto.HTTPConn{},
target: &gitproto.SSHConn{},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := sshStatsWarning(tt.cfg, tt.source, tt.target)
if (got != "") != tt.want {
t.Fatalf("sshStatsWarning() = %q, want warning=%t", got, tt.want)
}
})
}
}