func processTree(srv *context.T, h git.Hash, haves []git.Hash) (objs []git.Object, err error) { b, err := readObject(srv, h) if err != nil { return } tree := git.DecodeObject(b).(*git.Tree) objs = append(objs, tree) for i := range tree.Entries { entry := tree.Entries[i] var objects []git.Object b, err = readObject(srv, entry.Hash) if err != nil { return } obj := git.DecodeObject(b) switch obj.Type() { case "commit": objects, err = processCommit(srv, entry.Hash, haves) case "tree": objects, err = processTree(srv, entry.Hash, haves) case "blob": objects = []git.Object{obj} case "tag": objects = []git.Object{obj} } if err != nil { return } objs = append(objs, objects...) } return }
func processCommit(srv *context.T, want git.Hash, haves []git.Hash) (objs []git.Object, err error) { for i := range haves { if bytes.Compare(want, haves[i]) == 0 { return } } b, err := readObject(srv, want) if err != nil { return } commit := git.DecodeObject(b).(*git.Commit) objs = append(objs, commit) tree, err := processTree(srv, commit.Tree, haves) if err != nil { return } objs = append(objs, tree...) for i := range commit.Parents { var objects []git.Object objects, err = processCommit(srv, commit.Parents[i], haves) if err != nil { return } objs = append(objs, objects...) } return }
func (app *GitchainApp) OnDeliver(msg wendy.Message) { log := app.log var err error if msg.Purpose&MSG_BROADCAST != 0 { log.Debug("received a broadcast") if msg.Sender.ID == app.cluster.ID() { log.Error("received own broadcast", "bugtrap", "true") } var envelope broadcastEnvelope dec := gob.NewDecoder(bytes.NewBuffer(msg.Value)) dec.Decode(&envelope) if err != nil { log.Error("error while decoding an incoming message", "err", err) } else { var txe *transaction.Envelope if msg.Purpose&MSG_TRANSACTION != 0 { if txe, err = transaction.DecodeEnvelope(envelope.Content); err != nil { log.Error("error while decoding transaction", "err", err) } else { app.srv.Router.Pub(txe, "/transaction") log.Debug("announced transaction locally", "txn", txe) } } var newLimit wendy.NodeID nodes := app.cluster.RoutingTableNodes() if len(nodes) > 1 { for i := range nodes[0 : len(nodes)-1] { var buf bytes.Buffer enc := gob.NewEncoder(&buf) if nodes[i].ID.Less(envelope.Limit) { if nodes[i+1].ID.Less(envelope.Limit) { newLimit = nodes[i+1].ID } else { newLimit = envelope.Limit } if err = enc.Encode(broadcastEnvelope{Content: envelope.Content, Limit: newLimit}); err != nil { return } wmsg := app.cluster.NewMessage(msg.Purpose, nodes[i].ID, buf.Bytes()) if err = app.cluster.Send(wmsg); err != nil { log.Error("error sending message", "err", err) } else { log.Debug("forwarded transaction", "txn", txe) } } else { break } } } if nodes[len(nodes)-1].ID.Less(envelope.Limit) { var buf bytes.Buffer enc := gob.NewEncoder(&buf) if err = enc.Encode(broadcastEnvelope{Content: envelope.Content, Limit: app.cluster.ID()}); err != nil { return } wmsg := app.cluster.NewMessage(msg.Purpose, nodes[len(nodes)-1].ID, buf.Bytes()) if err = app.cluster.Send(wmsg); err != nil { log.Error("error sending message", "err", err) } else { log.Debug("forwarded transaction", "txn", txe) } } } } else { switch { case msg.Purpose&MSG_OBJECT != 0: obj := git.DecodeObject(msg.Value) err = git.WriteObject(obj, path.Join(app.srv.Config.General.DataPath, "objects")) if err != nil { log.Error("error while writing object", "obj", obj, "err", err) } } } }