@@ -6,12 +6,14 @@ import (
66 "net"
77 "os"
88 "path/filepath"
9+ "slices"
910 "time"
1011)
1112
1213type InstallOptions struct {
1314 ManifestURL string
14- Force bool // `rune install --force` to force re-download
15+ Force bool // `rune install --force` to force re-download
16+ Target []string // empty = all; StepRuneMCP | StepRuned
1517 Progress ProgressFunc
1618 Log func (format string , args ... any )
1719}
@@ -66,16 +68,22 @@ func Install(ctx context.Context, opts InstallOptions) (*Result, error) {
6668 Installed : map [string ]ArtifactInfo {},
6769 }
6870
71+ // Total step count
72+ total := 3 // all steps
73+ if len (opts .Target ) > 0 {
74+ total = 1 + len (opts .Target ) // manifest + num artifacts
75+ }
76+
6977 // Fetch manifest
70- logf ("[1/3 ] manifest: fetching from %s" , opts .ManifestURL )
78+ logf ("[1/%d ] manifest: fetching from %s" , total , opts .ManifestURL )
7179 manifest , err := FetchManifest (ctx , opts .ManifestURL )
7280 if err != nil {
7381 r .Failed [StepManifest ] = err .Error ()
7482 r .Status = "partial"
7583 return r , err
7684 }
7785 r .Completed = append (r .Completed , StepManifest )
78- logf ("[1/3 ] manifest: ok (rune-mcp %s, runed %s)" , manifest .RuneMCPVersion , manifest .RunedVersion )
86+ logf ("[1/%d ] manifest: ok (rune-mcp %s, runed %s)" , total , manifest .RuneMCPVersion , manifest .RunedVersion )
7987
8088 artifacts , err := manifest .ArtifactsForCurrentPlatform ()
8189 if err != nil {
@@ -95,19 +103,26 @@ func Install(ctx context.Context, opts InstallOptions) (*Result, error) {
95103 {StepRuneMCP , artifacts .RuneMCP , paths .RuneMCPBinary },
96104 }
97105
106+ // Filter install target
107+ if len (opts .Target ) > 0 {
108+ installs = slices .DeleteFunc (installs , func (in install ) bool {
109+ return ! slices .Contains (opts .Target , in .step )
110+ })
111+ }
112+
98113 for i , in := range installs {
99- stepNum := i + 2 // starting from [2/3]
114+ stepNum := i + 2 // step 1: manifest
100115 if ! opts .Force {
101116 if fileExists (in .dest ) {
102- logf ("[%d/3 ] %s: skipped (already at %s)" , stepNum , in .step , in .dest )
117+ logf ("[%d/%d ] %s: skipped (already at %s)" , stepNum , total , in .step , in .dest )
103118 r .Completed = append (r .Completed , in .step )
104119 r .Skipped = append (r .Skipped , in .step )
105120
106121 continue
107122 }
108123 }
109124
110- logf ("[%d/3 ] %s (%d bytes): downloading..." , stepNum , in .step , in .spec .Size )
125+ logf ("[%d/%d ] %s (%d bytes): downloading..." , stepNum , total , in .step , in .spec .Size )
111126 if err := installArtifact (ctx , paths , in .spec , in .dest , opts .Progress ); err != nil {
112127 r .Failed [in .step ] = err .Error ()
113128 r .Status = "partial"
@@ -118,29 +133,32 @@ func Install(ctx context.Context, opts InstallOptions) (*Result, error) {
118133 if info , statErr := os .Stat (in .dest ); statErr == nil {
119134 r .Installed [filepath .Base (in .dest )] = ArtifactInfo {Path : in .dest , Size : info .Size ()}
120135 }
121- logf ("[%d/3] %s: installed at %s" , stepNum , in .step , in .dest )
122- }
136+ logf ("[%d/%d] %s: installed at %s" , stepNum , total , in .step , in .dest )
137+ }
138+
139+ // Record install audit is only available with full `rune install` (no not allow partial record)
140+ if len (opts .Target ) == 0 {
141+ auditArtifacts := make (map [string ]InstalledArtifact , len (installs ))
142+ for _ , in := range installs {
143+ entry := InstalledArtifact {
144+ URL : in .spec .URL ,
145+ SHA256 : in .spec .SHA256 ,
146+ Path : in .dest ,
147+ Size : in .spec .Size ,
148+ }
123149
124- // Record install audit
125- auditArtifacts := make (map [string ]InstalledArtifact , len (installs ))
126- for _ , in := range installs {
127- entry := InstalledArtifact {
128- URL : in .spec .URL ,
129- SHA256 : in .spec .SHA256 ,
130- Path : in .dest ,
131- Size : in .spec .Size ,
132- }
150+ if info , statErr := os .Stat (in .dest ); statErr == nil {
151+ entry .Size = info .Size ()
152+ }
133153
134- if info , statErr := os .Stat (in .dest ); statErr == nil {
135- entry .Size = info .Size ()
154+ auditArtifacts [in .step ] = entry
136155 }
137156
138- auditArtifacts [in .step ] = entry
139- }
140- if err := WriteInstalledManifest (paths , opts .ManifestURL , manifest , auditArtifacts ); err != nil {
141- logf ("warning: installed.json write failed: %v" , err ) // not fatal error
142- } else {
143- logf ("audit: installed.json updated at %s" , paths .InstalledManifest )
157+ if err := WriteInstalledManifest (paths , opts .ManifestURL , manifest , auditArtifacts ); err != nil {
158+ logf ("warning: installed.json write failed: %v" , err ) // not fatal error
159+ } else {
160+ logf ("audit: installed.json updated at %s" , paths .InstalledManifest )
161+ }
144162 }
145163
146164 // Probe socket
0 commit comments