Internal API Reference
Overview
This document provides a comprehensive reference for cpm's internal Go packages and APIs. These packages form the core functionality that the CLI commands utilize. While primarily for internal use, they can be imported and used programmatically for building custom tooling.
Package Structure
internal/
├── config/ # Configuration management
├── db/ # Database operations
├── org/ # Organization management
├── repo/ # Repository operations
├── server/ # Server management
└── ssh/ # SSH key operations
config Package
Import: cpm/internal/config
Types
Config
type Config struct {
MainServer string // Main server address (user@host)
DataDir string // Local repository storage directory
SSHKeyPath string // Default SSH private key path
DatabasePath string // SQLite database file path
}
Functions
Init
func Init(cfgFile string) error
Initialize configuration system. Creates default config if not exists.
Parameters:
cfgFile: Path to config file (empty string for default)
Returns: error if initialization fails
Example:
if err := config.Init(""); err != nil {
log.Fatal(err)
}
Load
func Load() (*Config, error)
Load configuration from file.
Returns:
*Config: Configuration structerror: Loading error if any
Example:
cfg, err := config.Load()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Main server: %s\n", cfg.MainServer)
Save
func Save(cfg *Config) error
Save configuration to file.
Parameters:
cfg: Configuration to save
Returns: error if save fails
Example:
cfg.MainServer = "git@newserver.com"
if err := config.Save(cfg); err != nil {
log.Fatal(err)
}
OpenDB
func OpenDB(cfg *Config) (*sql.DB, error)
Open database connection.
Parameters:
cfg: Configuration with database path
Returns:
*sql.DB: Database connectionerror: Connection error if any
db Package
Import: cpm/internal/db
Types
DB
type DB struct {
// contains filtered or unexported fields
}
Database connection wrapper.
User
type User struct {
ID int64 `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
PublicKey string `json:"public_key,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
Organization
type Organization struct {
ID int64 `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
}
Repository
type Repository struct {
ID int64 `json:"id"`
Name string `json:"name"`
OrgID int64 `json:"org_id"`
Path string `json:"path"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
}
Functions
Open
func Open(dbPath string) (*DB, error)
Open database connection and initialize schema.
Parameters:
dbPath: Path to SQLite database file
Returns:
*DB: Database instanceerror: Connection/initialization error
Example:
db, err := db.Open("/path/to/cpm.db")
if err != nil {
log.Fatal(err)
}
defer db.Close()
CreateUser
func (db *DB) CreateUser(username, email, publicKey string) (int64, error)
Create new user.
Parameters:
username: Unique usernameemail: User email addresspublicKey: SSH public key (optional, can be empty)
Returns:
int64: New user IDerror: Creation error if any
Example:
userID, err := db.CreateUser("alice", "alice@example.com", "ssh-ed25519 AAAA...")
if err != nil {
log.Fatal(err)
}
CreateRepository
func (db *DB) CreateRepository(name, path string, orgID int64) (int64, error)
Create repository record.
Parameters:
name: Repository namepath: File system path to bare repositoryorgID: Organization ID
Returns:
int64: New repository IDerror: Creation error
CreateOrganization
func (db *DB) CreateOrganization(name, description string) (int64, error)
Create new organization.
Parameters:
name: Unique organization namedescription: Organization description
Returns:
int64: New organization IDerror: Creation error
repo Package
Import: cpm/internal/repo
Functions
InitRepo
func InitRepo(name, path string) error
Initialize bare git repository.
Parameters:
name: Repository namepath: Directory to create repository in
Returns: error if initialization fails
Example:
if err := repo.InitRepo("myproject", "/var/cpm/repos"); err != nil {
log.Fatal(err)
}
RepoExists
func RepoExists(path string) (bool, error)
Check if repository exists at path.
Parameters:
path: Repository path
Returns:
bool: true if existserror: Check error
ListLocal
func ListLocal(dataDir string) ([]string, error)
List repositories in local directory.
Parameters:
dataDir: Data directory to scan
Returns:
[]string: List of repository nameserror: List error
PushRepo
func PushRepo(repoPath, remotePath, sshKeyPath string) error
Push repository to remote using rsync.
Parameters:
repoPath: Local repository pathremotePath: Remote path (user@host:path format)sshKeyPath: SSH private key path
Returns: error if push fails
PullRepo
func PullRepo(remotePath, localPath, sshKeyPath string) error
Pull repository from remote using rsync.
Parameters:
remotePath: Remote path (user@host:path format)localPath: Local destination pathsshKeyPath: SSH private key path
Returns: error if pull fails
ssh Package
Import: cpm/internal/ssh
Functions
GenerateED25519KeyPair
func GenerateED25519KeyPair(name string) (*KeyPair, error)
Generate ed25519 SSH key pair.
Parameters:
name: Key name for file naming
Returns:
*KeyPair: Generated key pair infoerror: Generation error
Example:
keyPair, err := ssh.GenerateED25519KeyPair("main-server")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Private key: %s\n", keyPair.PrivateKeyPath)
DeployKey
func DeployKey(publicKey, server string) error
Deploy public key to server's authorized_keys.
Parameters:
publicKey: SSH public key contentserver: Server address (user@host format)
Returns: error if deployment fails
GetFingerprint
func GetFingerprint(publicKeyPath string) (string, error)
Calculate SSH key fingerprint.
Parameters:
publicKeyPath: Path to public key file
Returns:
string: Fingerprint (SHA256 format)error: Calculation error
server Package
Import: cpm/internal/server
Types
Server
type Server struct {
ID int64
Name string
Host string
Port int
User string
SSHKeyPath string
IsNeighbor bool
}
SyncManager
type SyncManager struct {
// contains filtered or unexported fields
}
Handles repository synchronization.
Functions
NewSyncManager
func NewSyncManager(serverManager *ServerManager, repoBasePath string) *SyncManager
Create sync manager instance.
Parameters:
serverManager: Server manager instancerepoBasePath: Base path for repositories
Returns: *SyncManager
SyncRepoTo
func (sm *SyncManager) SyncRepoTo(repoName, targetServer string) (*SyncResult, error)
Synchronize repository to server.
Parameters:
repoName: Repository nametargetServer: Target server name
Returns:
*SyncResult: Sync result with statisticserror: Sync error
Example:
result, err := syncMgr.SyncRepoTo("myrepo", "origin")
if err != nil {
log.Fatal(err)
}
fmt.Printf("Synced in %v\n", result.Duration)
Usage Examples
Complete Workflow Example
package main
import (
"log"
"cpm/internal/config"
"cpm/internal/db"
"cpm/internal/repo"
"cpm/internal/ssh"
)
func main() {
// Load configuration
if err := config.Init(""); err != nil {
log.Fatal(err)
}
cfg, err := config.Load()
if err != nil {
log.Fatal(err)
}
// Open database
database, err := db.Open(cfg.DatabasePath)
if err != nil {
log.Fatal(err)
}
defer database.Close()
// Create organization
orgID, err := database.CreateOrganization("engineering", "Engineering team")
if err != nil {
log.Fatal(err)
}
// Initialize repository
repoPath := cfg.DataDir + "/myproject.git"
if err := repo.InitRepo("myproject", repoPath); err != nil {
log.Fatal(err)
}
// Register in database
repoID, err := database.CreateRepository("myproject", repoPath, orgID)
if err != nil {
log.Fatal(err)
}
log.Printf("Created repository ID: %d\n", repoID)
}
Custom Repository Sync Tool
package main
import (
"log"
"cpm/internal/config"
"cpm/internal/repo"
)
func main() {
cfg, _ := config.Load()
repos, err := repo.ListLocal(cfg.DataDir)
if err != nil {
log.Fatal(err)
}
for _, repoName := range repos {
localPath := cfg.DataDir + "/" + repoName
remotePath := cfg.MainServer + ":" + cfg.DataDir + "/" + repoName
log.Printf("Syncing %s...\n", repoName)
if err := repo.PushRepo(localPath, remotePath, cfg.SSHKeyPath); err != nil {
log.Printf("Failed: %v\n", err)
continue
}
log.Printf("Success\n")
}
}
Error Handling
All functions return Go-style errors. Check and handle appropriately:
result, err := someFunction()
if err != nil {
// Handle error
log.Printf("Error: %v", err)
return err
}
// Use result
Thread Safety
- Database operations are thread-safe (SQLite serialized mode)
- Configuration loading is not thread-safe (load once, use everywhere)
- SSH operations are not thread-safe per connection
- Sync operations can run concurrently for different repositories