@@ -38,6 +38,8 @@ func NewRunner(cfg *config.Config, log *logger.Logger) *Runner {
3838}
3939
4040// formatEnv returns the restic env vars formatted as a copy-pasteable command prefix.
41+ // On Windows, outputs PowerShell syntax ($env:VAR="val"; ).
42+ // On Unix, outputs inline syntax (VAR=val ).
4143// If redact is true, secrets are masked with ***.
4244func (r * Runner ) formatEnv (redact bool ) string {
4345 secretKeys := map [string ]bool {
@@ -48,7 +50,7 @@ func (r *Runner) formatEnv(redact bool) string {
4850
4951 var parts []string
5052 for _ , pair := range r .cfg .ResticEnv () {
51- key , _ , ok := strings .Cut (pair , "=" )
53+ key , val , ok := strings .Cut (pair , "=" )
5254 if ! ok {
5355 continue
5456 }
@@ -60,11 +62,17 @@ func (r *Runner) formatEnv(redact bool) string {
6062 continue
6163 }
6264 if redact && secretKeys [key ] {
63- parts = append (parts , fmt .Sprintf ("%s=***" , key ))
65+ val = "***"
66+ }
67+ if runtime .GOOS == "windows" {
68+ parts = append (parts , fmt .Sprintf ("$env:%s=\" %s\" " , key , val ))
6469 } else {
65- parts = append (parts , pair )
70+ parts = append (parts , fmt . Sprintf ( "%s=%s" , key , val ) )
6671 }
6772 }
73+ if runtime .GOOS == "windows" {
74+ return strings .Join (parts , "; " )
75+ }
6876 return strings .Join (parts , " " )
6977}
7078
@@ -96,7 +104,13 @@ func (r *Runner) run(ctx context.Context, args ...string) (*Result, error) {
96104 cmd .Stdout = & stdout
97105 cmd .Stderr = & stderr
98106
99- fullCmd := fmt .Sprintf ("%s %s %s" , r .formatEnv (! r .Debug ), r .cfg .ResticBinary , strings .Join (args , " " ))
107+ envStr := r .formatEnv (! r .Debug )
108+ var fullCmd string
109+ if runtime .GOOS == "windows" {
110+ fullCmd = fmt .Sprintf ("%s; %s %s" , envStr , r .cfg .ResticBinary , strings .Join (args , " " ))
111+ } else {
112+ fullCmd = fmt .Sprintf ("%s %s %s" , envStr , r .cfg .ResticBinary , strings .Join (args , " " ))
113+ }
100114 r .log .Info ("running restic" , map [string ]any {
101115 "cmd" : fullCmd ,
102116 })
0 commit comments