@@ -126,11 +126,78 @@ func (s *Stacker) Sync(ctx context.Context) error {
126126 return op .Err ()
127127}
128128
129- func (s * Stacker ) Fix (ctx context.Context ) error {
129+ func (s * Stacker ) Fix (ctx context.Context , branches ... string ) error {
130130 op := op (s .git )
131131
132- // TODO: look for any refs/stacker/*/* branches
133- // TODO: no such local branch? -> delete tracking ref
132+ // TODO: this is hacky. refactor.
133+ if len (branches ) == 2 {
134+ branch := op .parseBranchName (branches [0 ])
135+ baseBranch := op .parseBranchName (branches [1 ])
136+ if baseSymrefName := branch .StackerBaseRefName (); op .hasRef (baseSymrefName ) {
137+ baseSymref := op .ref (baseSymrefName )
138+ if baseSymref .SymRefTarget () != baseBranch .RefName () {
139+ return op .Failf ("base branch already defined: %v" , baseSymref .SymRefTarget ())
140+ }
141+ } else {
142+ op .createSymref (branch .StackerBaseRefName (), baseBranch .RefName (), "stacker: set base branch" )
143+ }
144+ if startRefName := branch .StackerStartRefName (); op .hasRef (startRefName ) {
145+ // TODO: check if base or ancestor of base
146+ } else {
147+ forkpoint := op .forkpoint (baseBranch .RefName (), branch .RefName ())
148+ op .createRef (branch .StackerStartRefName (), forkpoint )
149+ }
150+ return nil
151+ } else if len (branches ) != 0 {
152+ return op .Failf ("invalid arguments: %v" , branches )
153+ }
154+
155+ op .snapshot ()
156+ for _ , branch := range op .trackedBranches () {
157+ if ! op .hasRef (branch .RefName ()) {
158+ if r := branch .StackerBaseRefName (); op .hasRef (r ) {
159+ op .deleteSymref (r )
160+ }
161+ if r := branch .StackerStartRefName (); op .hasRef (r ) {
162+ ref := op .ref (r )
163+ op .deleteRef (r , ref .ObjectName ())
164+ }
165+ if r := branch .StackerRemoteRefName (); op .hasRef (r ) {
166+ ref := op .ref (r )
167+ op .deleteRef (r , ref .ObjectName ())
168+ }
169+ }
170+ }
171+
172+ op .snapshot ()
173+ for _ , branch := range op .trackedBranches () {
174+ // for each existing branch that's somehow still being tracked:
175+ baseSymrefName := branch .StackerBaseRefName ()
176+ startRefName := branch .StackerStartRefName ()
177+ if op .hasRef (baseSymrefName ) {
178+ // there's a base symref
179+ if ! op .hasRef (startRefName ) {
180+ // but no start ref
181+ baseSymref := op .ref (branch .StackerBaseRefName ())
182+ if ! op .hasRef (baseSymref .SymRefTarget ()) {
183+ // TODO: base branch doesn't exist (anymore)
184+ continue
185+ }
186+ // figure out forkpoint from what the base symref points to and the branch
187+ // TODO: forkpoint can fail
188+ forkpoint := op .forkpoint (baseSymref .SymRefTarget (), branch .RefName ())
189+ // write the commit as start ref
190+ op .createRef (branch .StackerStartRefName (), forkpoint )
191+ }
192+ } else {
193+ // there's no base symref
194+ if op .hasRef (startRefName ) {
195+ // but there's a start ref
196+ // TODO: check for branch at that commit? consult reflog?
197+ }
198+ }
199+ }
200+
134201 // TODO: no /base/, but /start/ -> look for branch head at /start/, set /base/
135202 // TODO: no /start/, but /base/ -> use git merge-base to find fork point
136203 // TODO: no /start/ nor /base/ -> do nothing, offer explicit way to track
0 commit comments