func()

in internal/git/trace2/parser.go [115:209]


func (p *parser) parseEvent(event *jsonEvent) error {
	if _, ok := ignoredEvents[event.Name]; ok {
		return nil
	}

	if p.root != nil && p.currentNode == nil {
		// The situation where there are more leaving events than starting ones. That makes
		// the currentNode exits the root node of the tree while moving upward. For example:
		// [start, region_start, region_start, region_leaving, region_leaving, region_leaving]
		return fmt.Errorf("unmatched leaving event")
	}

	var trace *Trace
	eventTime, err := p.parseEventTime(p.currentNode, event)
	if err != nil {
		return fmt.Errorf("parsing event time: %w", err)
	}

	if p.root == nil {
		trace = &Trace{Thread: event.Thread, StartTime: eventTime, Name: "root"}
		p.root = trace
		p.currentNode = p.root
	}

	// Leaving events, don't create trace
	switch event.Name {
	case "atexit":
		p.currentNode.FinishTime = eventTime
		p.currentNode.SetMetadata("code", fmt.Sprintf("%d", event.Code))
		return nil
	case "child_exit":
		p.currentNode.FinishTime = eventTime
		p.currentNode.SetMetadata("code", fmt.Sprintf("%d", event.Code))
		p.currentNode = p.currentNode.Parent
		return nil
	case "region_leave":
		p.currentNode.FinishTime = eventTime
		p.currentNode = p.currentNode.Parent
		return nil
	}

	trace = &Trace{
		ChildID:    p.currentNode.ChildID,
		Thread:     event.Thread,
		StartTime:  eventTime,
		FinishTime: eventTime,
		Parent:     p.currentNode,
		Depth:      p.currentNode.Depth + 1,
	}
	if event.Msg != "" {
		trace.SetMetadata("msg", event.Msg)
	}
	p.currentNode.Children = append(p.currentNode.Children, trace)

	switch event.Name {
	case "version":
		trace.setName([]string{event.Name, event.Category, event.Label})
		trace.SetMetadata("exe", event.Exe)
		trace.SetMetadata("evt", event.Evt)
	case "def_repo":
		trace.setName([]string{event.Name, event.Category, event.Label})
		trace.SetMetadata("worktree", event.Worktree)
	case "start":
		trace.setName([]string{event.Name, event.Category, event.Label})
		trace.SetMetadata("argv", strings.Join(event.Argv, " "))
	case "child_start":
		trace.setName([]string{event.Name, event.Category, event.Label})
		trace.SetMetadata("argv", strings.Join(event.Argv, " "))
		trace.ChildID = fmt.Sprintf("%d", event.ChildID)
		p.currentNode = trace
	case "region_enter":
		trace.setName([]string{event.Category, event.Label})
		p.currentNode = trace
	case "data":
		trace.setName([]string{event.Name, event.Category, event.Label, event.DataKey})
		if event.DataValue != nil {
			var data string
			// When the event name is "data", we can unmarshal the data. This allows
			// easy data access later
			err := json.Unmarshal(*event.DataValue, &data)
			if err != nil {
				return fmt.Errorf("mismatched data value: %w", err)
			}
			trace.SetMetadata("data", data)
		}
	case "data_json":
		trace.setName([]string{event.Name, event.Category, event.Label, event.DataKey})
		if event.DataValue != nil {
			trace.SetMetadata("data", string(*event.DataValue))
		}
	default:
		trace.setName([]string{event.Name, event.Category, event.Label})
	}
	return nil
}