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.