craft your forge, build your project, grow your community freely
1---
2id: "4f8d"
3priority: 75
4sprint: ""
5assignee: null
6status: triage
7kind: issue
8---
910# Found ancestor rework
1112Today we need to `found acestor` when user push a new branch or force push an existing branch. All this code start in [ssh](../app/server/ssh.go).
1314## Problem
1516This method run through all branches and try to find previous commit. It's huge in terms of compute and not always true.
1718## Solution
1920After investigation go-git permit to add an observer on a packfile deserializer to store all data. This does nothing in term of computing and is every time exact.
2122## What to do?
2324In go git:
2526- be able to create a `NewServer` with an optional packfile.Observer in `go-git/plumbing/server/server.go`27- in the same file create a session with the observer `NewReceivePackSession` => `s.handler.NewReceivePackSession(sto, s.ob)`28- in the same file add it to the session `NewReceivePackSession` => `return &rpSession{ob:ob,...}`29- in the same file give the observer to the parser `ReceivePack` => `s.writePackfile(r, s.ob)`30- in the same file use it when write `writePackfile` => `packfile.UpdateObjectStorage(s.storer, r, ob)`31- finally use it in `plumbing/format/packfile/common.go` with `UpdateObjectStorage` => `p := NewParser(packfile, WithStorage(s), WithScannerObservers(ob))`3233In gitroot:
3435```golang
36type Observer struct {
37 previousType plumbing.ObjectType
38 logger logger.Logger
39}
4041func (*Observer) OnHeader(count uint32) error {
42returnnil43}
4445// OnInflatedObjectHeader is called for each object header read.
46func (o *Observer) OnInflatedObjectHeader(t plumbing.ObjectType, objSize int64, pos int64) error {
47 o.previousType = t
48if o.previousType == plumbing.CommitObject {
49 o.logger.Warn("header", logger.NewLoggerPair("type", t.String()), logger.NewLoggerPair("pos", pos))
50 }
51returnnil52}
5354// OnInflatedObjectContent is called for each decoded object.
55func (o *Observer) OnInflatedObjectContent(h plumbing.Hash, pos int64, crc uint32, content []byte) error {
56if o.previousType == plumbing.CommitObject {
57 o.logger.Warn("new hash", logger.NewLoggerPair("hash", h.String()), logger.NewLoggerPair("pos", pos))
58 }
59returnnil60}
6162// OnFooter is called when decoding is done.
63func (o *Observer) OnFooter(h plumbing.Hash) error {
64returnnil65}
66```6768then use it in [ssh](app/server/ssh.go) `handleReceivePack` with:
6970```golang
71o :=&Observer{logger: session.logger}
72svr := server.NewServer(ld, o)
73```7475## Remarks
7677I have played with it and it seams to give commits sorted from top to bottom.
7879Be carreful with multiple branch push because we don't know what commit is related to what branch.