package main import ( "context" "flag" "fmt" "io" "strings" "sub2api-cn-relay-manager/internal/overlay" "sub2api-cn-relay-manager/internal/pack" ) type applyHostOverlayFunc func(context.Context, applyHostOverlayCLIRequest) (overlay.ApplyResult, error) type applyHostOverlayCLIRequest struct { PackDir string ProviderID string HostVersion string SourceDir string OutputDir string TargetHost string OverlayID string } func parseApplyHostOverlayCLIArgs(args []string) (applyHostOverlayCLIRequest, error) { fs := flag.NewFlagSet("apply-host-overlay", flag.ContinueOnError) fs.SetOutput(io.Discard) var req applyHostOverlayCLIRequest fs.StringVar(&req.PackDir, "pack-dir", "", "") fs.StringVar(&req.ProviderID, "provider-id", "", "") fs.StringVar(&req.HostVersion, "host-version", "", "") fs.StringVar(&req.SourceDir, "source-dir", "", "") fs.StringVar(&req.OutputDir, "output-dir", "", "") fs.StringVar(&req.TargetHost, "target-host", "", "") fs.StringVar(&req.OverlayID, "overlay-id", "", "") if err := fs.Parse(args); err != nil { return applyHostOverlayCLIRequest{}, err } switch { case strings.TrimSpace(req.PackDir) == "": return applyHostOverlayCLIRequest{}, fmt.Errorf("--pack-dir is required") case strings.TrimSpace(req.ProviderID) == "": return applyHostOverlayCLIRequest{}, fmt.Errorf("--provider-id is required") case strings.TrimSpace(req.HostVersion) == "": return applyHostOverlayCLIRequest{}, fmt.Errorf("--host-version is required") case strings.TrimSpace(req.SourceDir) == "": return applyHostOverlayCLIRequest{}, fmt.Errorf("--source-dir is required") } return req, nil } func runApplyHostOverlay(ctx context.Context, req applyHostOverlayCLIRequest) (overlay.ApplyResult, error) { loadedPack, err := pack.LoadDir(req.PackDir) if err != nil { return overlay.ApplyResult{}, err } providerManifest, err := findProvider(loadedPack, req.ProviderID) if err != nil { return overlay.ApplyResult{}, err } targetHost := strings.TrimSpace(req.TargetHost) if targetHost == "" { targetHost = loadedPack.Manifest.TargetHost } resolvedOverlays, err := pack.ResolveApplicableHostOverlays(providerManifest, targetHost, req.HostVersion) if err != nil { return overlay.ApplyResult{}, err } if len(resolvedOverlays) == 0 { return overlay.ApplyResult{}, fmt.Errorf("no host overlays matched provider %q for host %q version %q", req.ProviderID, targetHost, req.HostVersion) } filteredOverlays, err := overlay.FilterOverlays(resolvedOverlays, req.OverlayID) if err != nil { return overlay.ApplyResult{}, err } return overlay.Apply(ctx, overlay.ApplyRequest{ PackDir: loadedPack.Dir, SourceDir: req.SourceDir, OutputDir: req.OutputDir, Overlays: filteredOverlays, }) }