Helix Core is now P4. Product user interfaces will be updated soon. Learn more >>

P4 API for Go Documentation | 2025.2

# P4MergeData struct

## Description

The `P4MergeData` struct provides a utility for managing and accessing information about merge operations in a P4 Server. It encapsulates details about the files involved in a merge, the actions taken by the user and the server, and the results of the merge process. This struct is typically used in conjunction with resolve operations, where conflicts between file versions need to be resolved.

## Table of Methods

The P4MergeData struct provides data of an individual merge during the execution of a p4 resolve command. Use P4MergeData as a parameter in the resolve handler for processing merge operations.

Method | Type | Description
--- | --- | ---
`YourName()` | String | Returns the name of "your" file in the merge. (File in workspace).
`ThierName()` | String | Returns the name of "their" file in the merge. (File in the depot).
`BaseName()` | String | Returns the name of "base" file in the merge. (File in the depot).
`YourPath()` | String | Returns the path of "your" file in the merge. (File in workspace).
`ThierPath()` | String | Returns the path of "their" file in the merge. (Temporary file on workstation into which `ThierName` has been loaded).
`BasePath()` | String | Returns the path of the base file in the merge. (Temporary file on workstation into which `BaseName` has been loaded).
`ResultPath()` | String | Returns the path to the merge result. (Temporary file on workstation into which the automatic merge performed by the server has been loaded).
`MergeHint()` | `P4MergeStatus` | Returns hint from server as to how user might best resolve merge.
`RunMerge()` | Bool | If the environment variable `P4MERGE` is defined, run it and return a boolean based on the return value of that program.
`IsActionResolve()` | Bool | Checks if the merge involves resolving an action.
`IsContentResolve()` | Bool | Checks if the merge involves resolving content.
`ActionType()` | `P4Message` | Returns the action type message for the merge.
`MergeAction()` | `P4Message` | Returns the merge action message for the merge.
`TheirAction()` | `P4Message` | Returns the "their" action message for the merge.
`YourAction()` | `P4Message` | Returns the "your" action message for the merge.
`String()` | String | Returns a string representation of the merge data.

## Example

Here is an example where the Standard Resolve Handler is run first, followed by the Branch Resolve Handler:

Copy

    package main

    import (
        "fmt"
        "os"
        "p4"
    )

    // Custom resolve handler
    type MyCustomResolveHandler struct{}

    func (h *MyCustomResolveHandler) Resolve(md P4MergeData) P4MergeStatus {
        fmt.Println("Your Name:", md.YourName())
        fmt.Println("Their Name:", md.TheirName())
        fmt.Println("Base Name:", md.BaseName())
        fmt.Println("Merge Hint:", md.MergeHint())
        fmt.Println("Info:", md.Info())
        return md.MergeHint()
    }

    // Custom action resolve handler
    type MyActionResolveHandler struct{}

    func (h *MyActionResolveHandler) Resolve(md P4MergeData) P4MergeStatus {
        fmt.Println("Your Action:", md.YourAction())
        fmt.Println("Their Action:", md.TheirAction())
        fmt.Println("Merge Action:", md.MergeAction())
        fmt.Println("Action Type:", md.ActionType())
        fmt.Println("Merge Hint:", md.MergeHint())
        fmt.Println("Info:", md.Info())
        return md.MergeHint()
    }

    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"
        p4api.RunSave("client", client_specs)
        p4api.SetClient("mytest")

        // Create a test directory
        testDir := "test_resolve"
        err = os.Mkdir(testDir, 0755)
        if err != nil {
            fmt.Println("Failed to create directory:", err)
            return
        }

        // Create and add a file
        filePath := fmt.Sprintf("%s/foo.txt", testDir)
        err = os.WriteFile(filePath, []byte("First Line!"), 0644)
        if err != nil {
            fmt.Println("Failed to create file:", err)
            return
        }
        _, err = p4api.Run("add", filePath)
        if err != nil {
            fmt.Println("Failed to add files:", err)
            return
        }

        // Submit the file
        changeSpec, err := p4api.RunFetch("change")
        if err != nil {
            fmt.Println("Failed to fetch change spec:", err)
            return
        }
        changeSpec["Description"] = "Initial submit"
        _, err = p4api.RunSubmit(changeSpec)
        if err != nil {
            fmt.Println("Failed to submit change:", err)
            return
        }

        // Edit the file and submit a second revision
        _, err = p4api.Run("edit", filePath)
        if err != nil {
            fmt.Println("Failed to edit files:", err)
            return
        }
        err = os.WriteFile(filePath, []byte("Second Line."), 0644)
        if err != nil {
            fmt.Println("Failed to edit file:", err)
            return
        }
        changeSpec, err = p4api.RunFetch("change")
        if err != nil {
            fmt.Println("Failed to fetch change spec:", err)
            return
        }
        changeSpec["Description"] = "Second submit"
        _, err = p4api.RunSubmit(changeSpec)
        if err != nil {
            fmt.Println("Failed to submit change:", err)
            return
        }

        // Sync to the first revision
        _, err = p4api.Run("sync", filePath+"#1")
        if err != nil {
            fmt.Println("Failed to sync files:", err)
            return
        }

        // Open the file for edit and sync to schedule a resolve
        _ err = p4api.Run("edit", filePath)
        if err != nil {
            fmt.Println("Failed to edit files:", err)
            return
        }

        // Sync to the latest revision to create a conflict
        _, err = p4api.Run("sync", filePath)
        if err != nil {
            fmt.Println("Failed to sync files:", err)
            return
        }

        // Run the Standard Resolve Handler
        fmt.Println("\nRunning Standard Resolve Handler...")
        standardHandler := &MyCustomResolveHandler{}
        p4api.SetResolveHandler(standardHandler)
        _, err = p4api.Run("resolve")
        if err != nil {
            fmt.Println("Resolve failed:", err)
            return
        }

        // Submit the resolved file
        changeSpec, err = p4api.RunFetch("change")
        if err != nil {
            fmt.Println("Failed to fetch change spec:", err)
            return
        }
        changeSpec["Description"] = "Standard resolve submit"
        _, err = p4api.RunSubmit(changeSpec)
        if err != nil {
            fmt.Println("Failed to submit resolved file:", err)
            return
        }

        _, err = p4api.Run("revert", "//...")
        if err != nil {
            fmt.Println("Failed to revert changes:", err)
            return
        }

        // Schedule a branch resolve
        targetFile := fmt.Sprintf("%s/bar.txt", testDir)
        _, err = p4api.Run("integ", "-Rb", filePath, targetFile)
        if err != nil {
            fmt.Println("Failed to run branch integrate:", err)
            return
        }

        // Verify that the branch resolve is scheduled
        resolvePreview, err := p4api.Run("resolve", "-n")
        if err != nil {
            fmt.Println("Failed to fetch resolve preview:", err)
            return
        }
        if len(resolvePreview) == 0 {
            fmt.Println("No resolves scheduled")
            return
        }

        // Run the Branch Resolve Handler
        fmt.Println("\nRunning Branch Resolve Handler...")
        branchHandler := &MyActionResolveHandler{}
        p4api.SetResolveHandler(branchHandler)
        _, err = p4api.Run("resolve")
        if err != nil {
            fmt.Println("Resolve failed:", err)
            return
        }

        // Submit the resolved branch
        changeSpec, err = p4api.RunFetch("change")
        if err != nil {
            fmt.Println("Failed to fetch change spec:", err)
            return
        }
        changeSpec["Description"] = "Branch resolve submit"
        _, err = p4api.RunSubmit(changeSpec)
        if err != nil {
            fmt.Println("Failed to submit resolved branch:", err)
            return
        }

        fmt.Println("Standard and Branch resolves completed successfully.")

        p4api.Disconnect()
    }

### Output:

Copy

    Running Standard Resolve Handler...
        Your Name: //mytest/test_resolve/foo.txt
        Their Name: //depot/test_resolve/foo.txt#2
        Base Name: //depot/test_resolve/foo.txt#1
        Merge Hint: 4
        Info: 0

    Running Branch Resolve Handler...
        Your Action: ignore
        Their Action: branch
        Merge Action:
        Action Type: Branch resolve
        Merge Hint: 4
        Info: 0
        Standard and Branch resolves completed successfully.

Your search for returned results