P4OutputHandler interface
Description
P4OutputHandler is an interface that provides access to streaming output from the server.
After defining the output handler, set P4.SetHandler() to an instance of a struct implementing P4OutputHandler (or use a custom handler) to enable callbacks.
By default, P4OutputHandler methods return P4OUTPUTHANDLER_REPORT for all output methods.
The different return options are:
| Value | Meaning |
|---|---|
|
|
Messages added to output. |
|
|
Output is handled by the handler (message is not added to the output). |
|
|
Operation is marked for cancellation, and the message is added to the output. |
Interface Methods
The P4OutputHandler interface provides access to streaming output from the server. Set P4.SetHandler() to an instance of a struct that is implementing P4OutputHandler to enable callbacks.
| Method | Description |
|---|---|
|
|
Handles binary data output from a Perforce command. |
|
|
Handles a Perforce message object, such as errors or warnings. |
|
|
Handles a dictionary of key-value pairs returned by a Perforce command. |
|
|
Handles plain text output from a Perforce command. |
|
|
Handles tracking data output from a Perforce command. |
|
|
Handles a dictionary representing a Perforce spec (e.g., client, label, etc.). |
Example
package main
import (
"fmt"
"os"
"p4"
)
// CustomOutputHandler implements P4OutputHandler to handle various outputs
type CustomOutputHandler struct {
statOutput []Dictionary
infoOutput []string
messageOutput []P4Message
binaryOutput [][]byte
}
// HandleStat processes dictionary output
func (h *CustomOutputHandler) HandleStat(dict Dictionary) P4OutputHandlerResult {
fmt.Println("\nHandleStat called with:", dict)
h.statOutput = append(h.statOutput, dict)
return P4OUTPUTHANDLER_HANDLED
}
// HandleText processes informational text output
func (h *CustomOutputHandler) HandleText(info string) P4OutputHandlerResult {
fmt.Println("\nHandleText called with:", info)
h.infoOutput = append(h.infoOutput, info)
return P4OUTPUTHANDLER_REPORT
}
// HandleMessage processes messages (e.g., warnings, errors)
func (h *CustomOutputHandler) HandleMessage(msg P4Message) P4OutputHandlerResult {
fmt.Println("\nHandleMessage called with:", msg.String())
h.messageOutput = append(h.messageOutput, msg)
return P4OUTPUTHANDLER_REPORT
}
// HandleBinary processes binary data output
func (h *CustomOutputHandler) HandleBinary(data []byte) P4OutputHandlerResult {
fmt.Println("\nHandleBinary called with binary data of length:", len(data))
h.binaryOutput = append(h.binaryOutput, data)
return P4OUTPUTHANDLER_REPORT
}
// HandleSpec processes spec data output
func (h *CustomOutputHandler) HandleSpec(data Dictionary) P4OutputHandlerResult {
return P4OUTPUTHANDLER_REPORT
}
// HandleTrack processes performance tracking data
func (h *CustomOutputHandler) HandleTrack(data string) P4OutputHandlerResult {
return P4OUTPUTHANDLER_REPORT
}
func main() {
// Initialize the Perforce client
p4api := p4.New()
defer p4api.Close()
// Connect to the P4 server
connected, err := p4api.Connect()
if err != nil || !connected {
fmt.Println("Failed to connect to P4 server:", err)
return
}
defer p4api.Disconnect()
client_specs, _ := p4api.RunFetch("client", "mytest")
client_specs["Root"] = "path/to/client/root"
_, err = p4api.RunSave("client", client_specs)
if err != nil {
fmt.Println("Failed to create to client: ", err)
return
}
p4api.SetClient("mytest")
// Create the directory "test_files"
err = os.Mkdir("handler_files", 0755)
if err != nil {
fmt.Println("Failed to create directory: %v", err)
return
}
//Add a text file
txtFilepath := "handler_files/foo.txt"
err = os.WriteFile(txtFilepath, []byte("This is a test file"), 0644)
if err != nil {
fmt.Println("Failed to create file %s: %v", txtFilepath, err)
return
}
_, err = p4api.Run("add", txtFilepath)
if err != nil {
fmt.Println("Failed to add text files:", err)
return
}
// Add a binary file
binFilePath := "handler_files/bar.bin"
binaryContent := []byte{0x42, 0x69, 0x6E, 0x61, 0x72, 0x79, 0x20, 0x64, 0x61, 0x74, 0x61} // Example binary content
err = os.WriteFile(binFilePath, binaryContent, 0644)
if err != nil {
fmt.Println("Failed to create binary file %s: %v", binFilePath, err)
return
}
_, err = p4api.Run("add", "-t", "binary", binFilePath)
if err != nil {
fmt.Println("Failed to add binary files:", err)
return
}
change_specs, err := p4api.RunFetch("change")
if err != nil {
fmt.Println("failed to get change dict: ", err)
}
change_specs["Description"] = "Add some test files\n"
_, err = p4api.RunSubmit(change_specs)
if err != nil {
fmt.Println("Failed to submit test files: ", err)
return
}
// Run a Perforce command (e.g., "print", "sync") to demonstrate the handler
// Create an instance of the custom output handler
handler := &CustomOutputHandler{}
p4api.SetHandler(handler)
_, err = p4api.Run("sync", "//depot/handler_files/...")
if err != nil {
fmt.Println("Failed to run sync files:", err)
return
}
_, err = p4api.Run("print", "//depot/handler_files/...")
if err != nil {
fmt.Println("Failed to run print files:", err)
return
}
p4api.SetHandler(nil)
fmt.Println("\nPrint the collected outputs...")
// Print the collected outputs
fmt.Println("\nCollected Stat Output:")
for _, dict := range handler.statOutput {
fmt.Println(dict)
}
fmt.Println("\nCollected Info Output:")
for _, info := range handler.infoOutput {
fmt.Println(info)
}
fmt.Println("\nCollected Message Output:")
for _, msg := range handler.messageOutput {
fmt.Println(msg.String())
}
fmt.Println("\nCollected Binary Output:")
for _, data := range handler.binaryOutput {
fmt.Printf("Binary data of length %d\n", len(data))
}
p4api.Disconnect()
}
Output:
HandleMessage called with: //depot/handler_files/... - file(s) up-to-date.
HandleStat called with: map[action:add change:1 depotFile://depot/handler_files/bar.bin fileSize:11 rev:1 time:1744202008 type:binary]
HandleBinary called with binary data of length: 11
HandleBinary called with binary data of length: 0
HandleStat called with: map[action:add change:1 depotFile://depot/handler_files/foo.txt fileSize:19 rev:1 time:1744202008 type:text]
HandleText called with: This is a test file
HandleText called with:
Print the collected outputs...
Collected Stat Output:
map[action:add change:1 depotFile://depot/handler_files/bar.bin fileSize:11 rev:1 time:1744202008 type:binary]
map[action:add change:1 depotFile://depot/handler_files/foo.txt fileSize:19 rev:1 time:1744202008 type:text]
Collected Info Output:
This is a test file
Collected Message Output:
//depot/handler_files/... - file(s) up-to-date.
Collected Binary Output:
Binary data of length 11
Binary data of length 0