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 |
|---|---|
|
|
This method initializes the progress indicator. The |
|
|
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 |
|
|
This method sets the total number of units the |
|
|
The |
|
|
This method is invoked when the progress context has completed. If failed is |
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 |
|---|---|---|
|
|
|
Files sent to the server. This represents the source path, that is, the local path to the file being sent. |
|
|
|
Files received from server. This represents the destination path, that is, the local path to the file being received. |
|
|
|
Files transmitted. |
|
|
|
Computation performed server-side. |
Example
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:
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