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

P4 API for Go Documentation | 2025.2

# P4Progress interface

## Description

P4Progress is an interface that provides access to progress indicators from the server.
After defining the progress handler, set `P4.SetProgress()` to an instance of a struct implementing P4Progress (or use a block-like approach with a custom handler) to enable callbacks.

You must implement all five of the following methods:

- `Init()`

- `Description()`

- `Update()`

- `Total()`

- `Done()`

This must be implemented even if the methods return `0`.

## Interface Methods

Method | Description
--- | ---
`Init(progress_type int) -> void` | This method initializes the progress indicator. The `progress_type` parameter defines the type of progress being reported, such as file transfer, computation, or other operations.
`Total(total int64) -> void` | This method provides a textual description of the progress being tracked. For file transfers, this description is often the depot file path. The units parameter specifies the unit of measurement (e.g., bytes, files, etc.) that will be used in subsequent calls to `Total(total int64)` and `Update(position int64)` to track the overall progress and current position, respectively.
`Description(desc string, units int) -> void` | This method sets the total number of units the `P4Progress` instance should expect. This is typically used when there is a defined target value, allowing progress to be tracked and displayed, such as in a progress bar..
`Update(position int64) -> void` | The `Update(position int64)` method is invoked whenever there is a progress update. If `Total(total int64)` has not been called, this method can be used to indicate ongoing activity, such as displaying a spinner or other visual feedback to show that work is in progress.
`Done(failed bool) -> void` | This method is invoked when the progress context has completed. If failed is `true`, it indicates that an error occurred and the operation was unsuccessful; otherwise, the operation was completed successfully.

## Progress Units

Progress Unit Type | Value
--- | ---
Unspecified | `0`
Percentage Complete | `1`
Number of files | `2`
KB (1024 bytes) | `3`
MB (1024*1024 bytes) | `4`
Number of deltas | `5`

## Progress Types

The following `ProgressTypes` can be reported:

Type | Value | Meaning
--- | --- | ---
`SendFile` | `1` | Files sent to the server. This represents the source path, that is, the local path to the file being sent.
`ReceiveFile` | `2` | Files received from server. This represents the destination path, that is, the local path to the file being received.
`FilesTransferring` | `3` | Files transmitted.
`Computation` | `4` | Computation performed server-side.

For more information on progress indicators from the server see the ClientProgress documentation.

## Example

Copy

    package main

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

    // SyncProgressHandler implements P4Progress to handle progress updates
    type SyncProgressHandler struct {
        progressType int
        description  string
        total        int64
        position     int64
        failed       bool
    }

    // Init initializes the progress handler with the progress type
    func (p *SyncProgressHandler) Init(progressType int) {
        p.progressType = progressType
        fmt.Printf("Progress initialized with type: %d\n", progressType)
    }

    // Description sets the description of the progress
    func (p *SyncProgressHandler) Description(desc string, units int) {
        p.description = desc
        fmt.Printf("Progress description: %s (units: %d)\n", desc, units)
    }

    // Total sets the total amount of work
    func (p *SyncProgressHandler) Total(total int64) {
        p.total = total
        fmt.Printf("Total work: %d\n", total)
    }

    // Update updates the current position of the progress
    func (p *SyncProgressHandler) Update(position int64) {
        p.position = position
        fmt.Printf("Progress updated: %d/%d\n", position, p.total)
    }

    // Done marks the progress as completed or failed
    func (p *SyncProgressHandler) Done(failed bool) {
        p.failed = failed
        if failed {
            fmt.Println("Progress failed.")
        } else {
            fmt.Println("Progress completed successfully.")
        }
    }

    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 a test directory
        testDir := "progress_test_files"
        err = os.Mkdir(testDir, 0755)
        if err != nil {
            fmt.Println("Failed to create directory:", err)
            return
        }

        // Create and add test files
        totalFiles := 10
        for i := 0; i < totalFiles; i++ {
            filePath := fmt.Sprintf("%s/file%d.txt", testDir, i)
            err := os.WriteFile(filePath, []byte(strings.Repeat("Test content\n", 10)), 0644)
            if err != nil {
                fmt.Printf("Failed to create file %s: %v\n", filePath, err)
                return
            }
            _, err = p4api.Run("add", filePath)
            if err != nil {
                fmt.Println("Failed to run add files:", err)
                return
            }
        }

        // Submit the files
        changeSpec, err := p4api.RunFetch("change")
        if err != nil {
            fmt.Println("Failed to fetch change spec:", err)
            return
        }
        changeSpec["Description"] = "Add test files for progress demonstration"
        _, err = p4api.RunSubmit(changeSpec)
        if err != nil {
            fmt.Println("Failed to submit changes:", err)
            return
        }
        _, err = p4api.Run("sync", "//depot/progress_test_files/...#0")
        if err != nil {
            fmt.Println("Failed to run sync files:", err)
            return
        }

        // Create an instance of the progress handler
        progressHandler := &SyncProgressHandler{}
        p4api.SetProgress(progressHandler)

        // Run the sync command
        fmt.Println("Running 'sync' command...")
        _, err = p4api.Run("sync", "-q", fmt.Sprintf("//depot/%s/...", testDir))
        if err != nil {
            fmt.Println("Failed to run sync files:", err)
            return
        }

        p4api.SetProgress(nil)

        // Print the final progress state
        fmt.Printf("\nFinal Progress State:\n")
        fmt.Printf("Type: %d\n", progressHandler.progressType)
        fmt.Printf("Description: %s\n", progressHandler.description)
        fmt.Printf("Total: %d\n", progressHandler.total)
        fmt.Printf("Position: %d\n", progressHandler.position)
        fmt.Printf("Failed: %v\n", progressHandler.failed)
    }

### Output:

Copy

    Running 'sync' command...
    Progress initialized with type: 3
    Progress description: sync (units: 0)
    Total work: 10
    Progress updated: 10/10
    Progress failed.

    Final Progress State:
    Type: 3
    Description: sync
    Total: 10
    Position: 10
    Failed: true

Your search for returned results