Craft your forge, Build your project, Grow your community freely
1---
2id: "4f8d"
3priority: 75
4assignee: null
5status: v0.5.0
6---
7 8# Found ancestor rework
910Today 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).
1112## Problem
1314This method run through all branches and try to find previous commit. It's huge in terms of compute and not always true.
1516## Solution
1718After 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.
1920## What to do?
2122In go git:
2324- be able to create a `NewServer` with an optional packfile.Observer in `go-git/plumbing/server/server.go`25- in the same file create a session with the observer `NewReceivePackSession` => `s.handler.NewReceivePackSession(sto, s.ob)`26- in the same file add it to the session `NewReceivePackSession` => `return &rpSession{ob:ob,...}`27- in the same file give the observer to the parser `ReceivePack` => `s.writePackfile(r, s.ob)`28- in the same file use it when write `writePackfile` => `packfile.UpdateObjectStorage(s.storer, r, ob)`29- finally use it in `plumbing/format/packfile/common.go` with `UpdateObjectStorage` => `p := NewParser(packfile, WithStorage(s), WithScannerObservers(ob))`3031In gitroot:
3233```golang
34type Observer struct {
35 previousType plumbing.ObjectType
36 logger logger.Logger
37}
3839func (*Observer) OnHeader(count uint32) error {
40returnnil41}
4243// OnInflatedObjectHeader is called for each object header read.
44func (o *Observer) OnInflatedObjectHeader(t plumbing.ObjectType, objSize int64, pos int64) error {
45 o.previousType = t
46if o.previousType == plumbing.CommitObject {
47 o.logger.Warn("header", logger.NewLoggerPair("type", t.String()), logger.NewLoggerPair("pos", pos))
48 }
49returnnil50}
5152// OnInflatedObjectContent is called for each decoded object.
53func (o *Observer) OnInflatedObjectContent(h plumbing.Hash, pos int64, crc uint32, content []byte) error {
54if o.previousType == plumbing.CommitObject {
55 o.logger.Warn("new hash", logger.NewLoggerPair("hash", h.String()), logger.NewLoggerPair("pos", pos))
56 }
57returnnil58}
5960// OnFooter is called when decoding is done.
61func (o *Observer) OnFooter(h plumbing.Hash) error {
62returnnil63}
64```6566then use it in [ssh](app/server/ssh.go) `handleReceivePack` with:
6768```golang
69o :=&Observer{logger: session.logger}
70svr := server.NewServer(ld, o)
71```7273## Remarks
7475I have played with it and it seams to give commits sorted from top to bottom.
7677Be carreful with multiple branch push because we don't know what commit is related to what branch.