@@ -18,6 +18,8 @@ import (
1818 "context"
1919 "fmt"
2020 "os"
21+ "os/exec"
22+ "strings"
2123
2224 "github.com/chainguard-dev/clog"
2325 "github.com/go-git/go-git/v5"
@@ -28,6 +30,7 @@ type GitCheckoutOptions struct {
2830 Repository string
2931 Destination string
3032 ExpectedCommit string
33+ CherryPicks string
3134}
3235
3336func GitCheckout (ctx context.Context , opts * GitCheckoutOptions ) error {
@@ -77,5 +80,70 @@ func GitCheckout(ctx context.Context, opts *GitCheckoutOptions) error {
7780
7881 log .Infof ("Checked out commit %s" , head .Hash ().String ())
7982
83+ // Apply cherry-picks if specified
84+ if opts .CherryPicks != "" {
85+ log .Infof ("Applying cherry-picks" )
86+ picks , err := parseCherryPicks (opts .CherryPicks )
87+ if err != nil {
88+ return fmt .Errorf ("failed to parse cherry-picks: %w" , err )
89+ }
90+
91+ if err := applyCherryPicks (ctx , opts .Destination , picks ); err != nil {
92+ return fmt .Errorf ("failed to apply cherry-picks: %w" , err )
93+ }
94+ }
95+
96+ return nil
97+ }
98+
99+ func parseCherryPicks (input string ) ([]string , error ) {
100+ var commits []string
101+ lines := strings .Split (input , "\n " )
102+
103+ for _ , line := range lines {
104+ // Trim whitespace
105+ line = strings .TrimSpace (line )
106+
107+ // Skip empty lines and comments
108+ if line == "" || strings .HasPrefix (line , "#" ) {
109+ continue
110+ }
111+
112+ // Parse format: [branch/]commit: comment
113+ // We only care about the commit hash
114+ parts := strings .SplitN (line , ":" , 2 )
115+ if len (parts ) != 2 {
116+ return nil , fmt .Errorf ("invalid cherry-pick format (expected '[branch/]commit: comment'): %s" , line )
117+ }
118+
119+ pickSpec := strings .TrimSpace (parts [0 ])
120+
121+ // Strip optional branch prefix (we don't need it with full clone)
122+ commit := pickSpec
123+ if slashIdx := strings .Index (pickSpec , "/" ); slashIdx != - 1 {
124+ commit = pickSpec [slashIdx + 1 :]
125+ }
126+
127+ commits = append (commits , commit )
128+ }
129+
130+ return commits , nil
131+ }
132+
133+ func applyCherryPicks (ctx context.Context , repoPath string , commits []string ) error {
134+ log := clog .FromContext (ctx )
135+
136+ for _ , commit := range commits {
137+ log .Infof ("Cherry-picking %s" , commit )
138+
139+ cmd := exec .CommandContext (ctx , "git" , "cherry-pick" , "-x" , commit )
140+ cmd .Dir = repoPath
141+ cmd .Stdout = os .Stdout
142+ cmd .Stderr = os .Stderr
143+ if err := cmd .Run (); err != nil {
144+ return fmt .Errorf ("failed to cherry-pick %s: %w" , commit , err )
145+ }
146+ }
147+
80148 return nil
81149}
0 commit comments