github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/internal/runners/swtch/switch.go (about)

     1  package swtch
     2  
     3  import (
     4  	"github.com/ActiveState/cli/internal/analytics"
     5  	"github.com/ActiveState/cli/internal/config"
     6  	"github.com/ActiveState/cli/internal/errs"
     7  	"github.com/ActiveState/cli/internal/locale"
     8  	"github.com/ActiveState/cli/internal/logging"
     9  	"github.com/ActiveState/cli/internal/output"
    10  	"github.com/ActiveState/cli/internal/primer"
    11  	"github.com/ActiveState/cli/internal/rtutils/ptr"
    12  	"github.com/ActiveState/cli/internal/runbits/rationalize"
    13  	"github.com/ActiveState/cli/internal/runbits/runtime"
    14  	"github.com/ActiveState/cli/pkg/localcommit"
    15  	"github.com/ActiveState/cli/pkg/platform/api/mono/mono_models"
    16  	"github.com/ActiveState/cli/pkg/platform/authentication"
    17  	"github.com/ActiveState/cli/pkg/platform/model"
    18  	"github.com/ActiveState/cli/pkg/platform/runtime/target"
    19  	"github.com/ActiveState/cli/pkg/project"
    20  	"github.com/go-openapi/strfmt"
    21  )
    22  
    23  type Switch struct {
    24  	auth      *authentication.Auth
    25  	out       output.Outputer
    26  	project   *project.Project
    27  	analytics analytics.Dispatcher
    28  	svcModel  *model.SvcModel
    29  	cfg       *config.Instance
    30  }
    31  
    32  type SwitchParams struct {
    33  	Identifier string
    34  }
    35  
    36  type primeable interface {
    37  	primer.Auther
    38  	primer.Outputer
    39  	primer.Projecter
    40  	primer.Configurer
    41  	primer.Analyticer
    42  	primer.SvcModeler
    43  }
    44  
    45  type identifier interface {
    46  	CommitID() strfmt.UUID
    47  	Locale() string
    48  }
    49  
    50  type commitIdentifier struct {
    51  	commitID strfmt.UUID
    52  }
    53  
    54  func (c commitIdentifier) CommitID() strfmt.UUID {
    55  	return c.commitID
    56  }
    57  
    58  func (c commitIdentifier) Locale() string {
    59  	return locale.Tl("commit_identifier_type", "commit")
    60  }
    61  
    62  type branchIdentifier struct {
    63  	branch *mono_models.Branch
    64  }
    65  
    66  func (b branchIdentifier) CommitID() strfmt.UUID {
    67  	return *b.branch.CommitID
    68  }
    69  
    70  func (b branchIdentifier) Locale() string {
    71  	return locale.Tl("branch_identifier_type", "branch")
    72  }
    73  
    74  func New(prime primeable) *Switch {
    75  	return &Switch{
    76  		auth:      prime.Auth(),
    77  		out:       prime.Output(),
    78  		project:   prime.Project(),
    79  		analytics: prime.Analytics(),
    80  		svcModel:  prime.SvcModel(),
    81  		cfg:       prime.Config(),
    82  	}
    83  }
    84  
    85  func (s *Switch) Run(params SwitchParams) error {
    86  	logging.Debug("ExecuteSwitch")
    87  
    88  	if s.project == nil {
    89  		return rationalize.ErrNoProject
    90  	}
    91  	s.out.Notice(locale.Tr("operating_message", s.project.NamespaceString(), s.project.Dir()))
    92  
    93  	project, err := model.LegacyFetchProjectByName(s.project.Owner(), s.project.Name())
    94  	if err != nil {
    95  		return locale.WrapError(err, "err_fetch_project", "", s.project.Namespace().String())
    96  	}
    97  
    98  	identifier, err := resolveIdentifier(project, params.Identifier)
    99  	if err != nil {
   100  		return locale.WrapError(err, "err_resolve_identifier", "Could not resolve identifier '{{.V0}}'", params.Identifier)
   101  	}
   102  
   103  	if id, ok := identifier.(branchIdentifier); ok {
   104  		err = s.project.Source().SetBranch(id.branch.Label)
   105  		if err != nil {
   106  			return locale.WrapError(err, "err_switch_set_branch", "Could not update branch")
   107  		}
   108  	}
   109  
   110  	belongs, err := model.CommitBelongsToBranch(s.project.Owner(), s.project.Name(), s.project.BranchName(), identifier.CommitID(), s.auth)
   111  	if err != nil {
   112  		return locale.WrapError(err, "err_identifier_branch", "Could not determine if commit belongs to branch")
   113  	}
   114  	if !belongs {
   115  		return locale.NewInputError("err_identifier_branch_not_on_branch", "Commit does not belong to history for branch [ACTIONABLE]{{.V0}}[/RESET]", s.project.BranchName())
   116  	}
   117  
   118  	err = localcommit.Set(s.project.Dir(), identifier.CommitID().String())
   119  	if err != nil {
   120  		return errs.Wrap(err, "Unable to set local commit")
   121  	}
   122  
   123  	_, err = runtime.SolveAndUpdate(s.auth, s.out, s.analytics, s.project, ptr.To(identifier.CommitID()), target.TriggerSwitch, s.svcModel, s.cfg, runtime.OptNone)
   124  	if err != nil {
   125  		return locale.WrapError(err, "err_refresh_runtime")
   126  	}
   127  
   128  	s.out.Print(output.Prepare(
   129  		locale.Tl("branch_switch_success", "Successfully switched to {{.V0}}: [NOTICE]{{.V1}}[/RESET]", identifier.Locale(), params.Identifier),
   130  		&struct {
   131  			Branch string `json:"branch"`
   132  		}{
   133  			params.Identifier,
   134  		},
   135  	))
   136  
   137  	return nil
   138  }
   139  
   140  func resolveIdentifier(project *mono_models.Project, idParam string) (identifier, error) {
   141  	if strfmt.IsUUID(idParam) {
   142  		return commitIdentifier{strfmt.UUID(idParam)}, nil
   143  	}
   144  
   145  	branch, err := model.BranchForProjectByName(project, idParam)
   146  	if err != nil {
   147  		return nil, locale.WrapError(err, "err_identifier_branch", "Could not get branch '{{.V0}}' for current project", idParam)
   148  
   149  	}
   150  
   151  	return branchIdentifier{branch: branch}, nil
   152  }