996 lines
29 KiB
Go
996 lines
29 KiB
Go
package template
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
"time"
|
|
)
|
|
|
|
// VersionManager manages template versioning and rollback
|
|
type VersionManager struct {
|
|
basePath string
|
|
versions map[string][]VersionInfo
|
|
logger *slog.Logger
|
|
}
|
|
|
|
// VersionInfo holds information about a template version
|
|
type VersionInfo struct {
|
|
Version string `json:"version"`
|
|
Timestamp time.Time `json:"timestamp"`
|
|
FilePath string `json:"file_path"`
|
|
Hash string `json:"hash"`
|
|
Description string `json:"description"`
|
|
Author string `json:"author"`
|
|
Size int64 `json:"size"`
|
|
Active bool `json:"active"`
|
|
}
|
|
|
|
// VersionHistory holds the complete version history for a template
|
|
type VersionHistory struct {
|
|
TemplateName string `json:"template_name"`
|
|
Versions []VersionInfo `json:"versions"`
|
|
Current VersionInfo `json:"current"`
|
|
}
|
|
|
|
// NewVersionManager creates a new version manager
|
|
func NewVersionManager(basePath string) *VersionManager {
|
|
return &VersionManager{
|
|
basePath: basePath,
|
|
versions: make(map[string][]VersionInfo),
|
|
logger: slog.With("component", "version_manager"),
|
|
}
|
|
}
|
|
|
|
// SaveVersion saves a new version of a template
|
|
func (vm *VersionManager) SaveVersion(templateName, templatePath, description, author string) error {
|
|
// Create versions directory
|
|
versionsDir := filepath.Join(vm.basePath, "versions", templateName)
|
|
if err := os.MkdirAll(versionsDir, 0755); err != nil {
|
|
return fmt.Errorf("failed to create versions directory: %w", err)
|
|
}
|
|
|
|
// Generate version info
|
|
version := vm.generateVersion()
|
|
versionFile := filepath.Join(versionsDir, fmt.Sprintf("%s_%s.html", templateName, version))
|
|
|
|
// Read current template content
|
|
content, err := os.ReadFile(templatePath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read template: %w", err)
|
|
}
|
|
|
|
// Calculate hash
|
|
hash := vm.calculateHash(content)
|
|
|
|
// Get file info
|
|
info, err := os.Stat(templatePath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get file info: %w", err)
|
|
}
|
|
|
|
// Create version info
|
|
versionInfo := VersionInfo{
|
|
Version: version,
|
|
Timestamp: time.Now(),
|
|
FilePath: versionFile,
|
|
Hash: hash,
|
|
Description: description,
|
|
Author: author,
|
|
Size: info.Size(),
|
|
Active: true,
|
|
}
|
|
|
|
// Save template content
|
|
if err := os.WriteFile(versionFile, content, 0644); err != nil {
|
|
return fmt.Errorf("failed to save version: %w", err)
|
|
}
|
|
|
|
// Update versions map
|
|
if vm.versions[templateName] == nil {
|
|
vm.versions[templateName] = []VersionInfo{}
|
|
}
|
|
|
|
// Deactivate previous versions
|
|
for i := range vm.versions[templateName] {
|
|
vm.versions[templateName][i].Active = false
|
|
}
|
|
|
|
vm.versions[templateName] = append(vm.versions[templateName], versionInfo)
|
|
|
|
// Persist version metadata
|
|
if err := vm.saveVersionMetadata(templateName); err != nil {
|
|
vm.logger.Warn("failed to save version metadata", "error", err)
|
|
}
|
|
|
|
vm.logger.Info("template version saved",
|
|
"template", templateName,
|
|
"version", version,
|
|
"author", author)
|
|
|
|
return nil
|
|
}
|
|
|
|
// Rollback rolls back to a specific version
|
|
func (vm *VersionManager) Rollback(templateName, version string) error {
|
|
versions := vm.versions[templateName]
|
|
if len(versions) == 0 {
|
|
return fmt.Errorf("no versions found for template: %s", templateName)
|
|
}
|
|
|
|
var targetVersion *VersionInfo
|
|
for i := range versions {
|
|
if versions[i].Version == version {
|
|
targetVersion = &versions[i]
|
|
break
|
|
}
|
|
}
|
|
|
|
if targetVersion == nil {
|
|
return fmt.Errorf("version %s not found for template %s", version, templateName)
|
|
}
|
|
|
|
// Read version content
|
|
content, err := os.ReadFile(targetVersion.FilePath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read version content: %w", err)
|
|
}
|
|
|
|
// Write to current template
|
|
currentPath := filepath.Join(vm.basePath, templateName+".html")
|
|
if err := os.WriteFile(currentPath, content, 0644); err != nil {
|
|
return fmt.Errorf("failed to restore version: %w", err)
|
|
}
|
|
|
|
// Update active state
|
|
for i := range versions {
|
|
versions[i].Active = versions[i].Version == version
|
|
}
|
|
|
|
vm.logger.Info("template rolled back", "template", templateName, "version", version)
|
|
return nil
|
|
}
|
|
|
|
// GetVersionHistory returns the version history for a template
|
|
func (vm *VersionManager) GetVersionHistory(templateName string) (*VersionHistory, error) {
|
|
versions := vm.versions[templateName]
|
|
if len(versions) == 0 {
|
|
return nil, fmt.Errorf("no versions found for template: %s", templateName)
|
|
}
|
|
|
|
var current VersionInfo
|
|
for _, v := range versions {
|
|
if v.Active {
|
|
current = v
|
|
break
|
|
}
|
|
}
|
|
|
|
return &VersionHistory{
|
|
TemplateName: templateName,
|
|
Versions: versions,
|
|
Current: current,
|
|
}, nil
|
|
}
|
|
|
|
// ListTemplates returns all templates with versions
|
|
func (vm *VersionManager) ListTemplates() map[string][]VersionInfo {
|
|
return vm.versions
|
|
}
|
|
|
|
// DeleteVersion deletes a specific version
|
|
func (vm *VersionManager) DeleteVersion(templateName, version string) error {
|
|
versions := vm.versions[templateName]
|
|
if len(versions) == 0 {
|
|
return fmt.Errorf("no versions found for template: %s", templateName)
|
|
}
|
|
|
|
var newVersions []VersionInfo
|
|
for _, v := range versions {
|
|
if v.Version != version {
|
|
newVersions = append(newVersions, v)
|
|
} else {
|
|
// Remove file
|
|
if err := os.Remove(v.FilePath); err != nil && !os.IsNotExist(err) {
|
|
vm.logger.Warn("failed to delete version file", "file", v.FilePath, "error", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
vm.versions[templateName] = newVersions
|
|
vm.logger.Info("template version deleted", "template", templateName, "version", version)
|
|
return nil
|
|
}
|
|
|
|
// CleanupOldVersions removes old versions beyond retention limit
|
|
func (vm *VersionManager) CleanupOldVersions(templateName string, retentionCount int) error {
|
|
versions := vm.versions[templateName]
|
|
if len(versions) <= retentionCount {
|
|
return nil
|
|
}
|
|
|
|
// Sort by timestamp (newest first)
|
|
sorted := make([]VersionInfo, len(versions))
|
|
copy(sorted, versions)
|
|
|
|
// Keep only the latest versions
|
|
vm.versions[templateName] = sorted[:retentionCount]
|
|
|
|
// Delete old files
|
|
for _, v := range sorted[retentionCount:] {
|
|
if err := os.Remove(v.FilePath); err != nil && !os.IsNotExist(err) {
|
|
vm.logger.Warn("failed to delete old version file", "file", v.FilePath, "error", err)
|
|
}
|
|
}
|
|
|
|
vm.logger.Info("old versions cleaned up", "template", templateName, "kept", retentionCount, "deleted", len(sorted)-retentionCount)
|
|
return nil
|
|
}
|
|
|
|
// generateVersion generates a unique version identifier
|
|
func (vm *VersionManager) generateVersion() string {
|
|
return time.Now().Format("20060102_150405")
|
|
}
|
|
|
|
// calculateHash calculates a simple hash for content
|
|
func (vm *VersionManager) calculateHash(content []byte) string {
|
|
// Simple hash - in production, use a proper hash function
|
|
return fmt.Sprintf("%x", len(content))
|
|
}
|
|
|
|
// saveVersionMetadata saves version metadata to disk
|
|
func (vm *VersionManager) saveVersionMetadata(templateName string) error {
|
|
// This could be implemented to persist metadata to a JSON file
|
|
// For now, it's kept in memory
|
|
return nil
|
|
}
|
|
|
|
// LoadVersionMetadata loads version metadata from disk
|
|
func (vm *VersionManager) LoadVersionMetadata() error {
|
|
// This could be implemented to load metadata from a JSON file
|
|
// For now, it's kept in memory
|
|
return nil
|
|
}
|
|
|
|
// GetTemplateStats returns statistics for a template
|
|
func (vm *VersionManager) GetTemplateStats(templateName string) map[string]interface{} {
|
|
versions := vm.versions[templateName]
|
|
stats := map[string]interface{}{
|
|
"total_versions": len(versions),
|
|
"current_version": "",
|
|
"oldest_version": "",
|
|
"newest_version": "",
|
|
"total_size": int64(0),
|
|
}
|
|
|
|
if len(versions) > 0 {
|
|
stats["current_version"] = versions[len(versions)-1].Version
|
|
stats["oldest_version"] = versions[0].Version
|
|
stats["newest_version"] = versions[len(versions)-1].Version
|
|
|
|
var totalSize int64
|
|
for _, v := range versions {
|
|
totalSize += v.Size
|
|
}
|
|
stats["total_size"] = totalSize
|
|
}
|
|
|
|
return stats
|
|
}
|
|
|
|
// ExportVersion exports a specific version to a file
|
|
func (vm *VersionManager) ExportVersion(templateName, version, exportPath string) error {
|
|
versions := vm.versions[templateName]
|
|
|
|
var versionInfo *VersionInfo
|
|
for _, v := range versions {
|
|
if v.Version == version {
|
|
versionInfo = &v
|
|
break
|
|
}
|
|
}
|
|
|
|
if versionInfo == nil {
|
|
return fmt.Errorf("version %s not found for template %s", version, templateName)
|
|
}
|
|
|
|
content, err := os.ReadFile(versionInfo.FilePath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read version content: %w", err)
|
|
}
|
|
|
|
if err := os.WriteFile(exportPath, content, 0644); err != nil {
|
|
return fmt.Errorf("failed to export version: %w", err)
|
|
}
|
|
|
|
vm.logger.Info("template version exported", "template", templateName, "version", version, "export_path", exportPath)
|
|
return nil
|
|
}
|
|
|
|
// ImportVersion imports a template from a file
|
|
func (vm *VersionManager) ImportVersion(templateName, importPath, description, author string) error {
|
|
if _, err := os.Stat(importPath); os.IsNotExist(err) {
|
|
return fmt.Errorf("import file does not exist: %s", importPath)
|
|
}
|
|
|
|
return vm.SaveVersion(templateName, importPath, description, author)
|
|
}
|
|
|
|
// GetStoragePath returns the storage path for versions
|
|
func (vm *VersionManager) GetStoragePath(templateName string) string {
|
|
return filepath.Join(vm.basePath, "versions", templateName)
|
|
}
|
|
|
|
// ValidateVersion validates a version before saving
|
|
func (vm *VersionManager) ValidateVersion(templatePath string) error {
|
|
if _, err := os.Stat(templatePath); os.IsNotExist(err) {
|
|
return fmt.Errorf("template file does not exist: %s", templatePath)
|
|
}
|
|
|
|
// Add more validation as needed
|
|
return nil
|
|
}
|
|
|
|
// GetAllTemplatesWithVersions returns all templates and their versions
|
|
func (vm *VersionManager) GetAllTemplatesWithVersions() map[string]interface{} {
|
|
result := make(map[string]interface{})
|
|
|
|
for templateName := range vm.versions {
|
|
stats := vm.GetTemplateStats(templateName)
|
|
history, _ := vm.GetVersionHistory(templateName)
|
|
|
|
result[templateName] = map[string]interface{}{
|
|
"stats": stats,
|
|
"history": history,
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// BackupAllTemplates creates a backup of all templates
|
|
func (vm *VersionManager) BackupAllTemplates(backupPath string) error {
|
|
if err := os.MkdirAll(backupPath, 0755); err != nil {
|
|
return fmt.Errorf("failed to create backup directory: %w", err)
|
|
}
|
|
|
|
for templateName := range vm.versions {
|
|
versions := vm.versions[templateName]
|
|
for _, version := range versions {
|
|
backupFile := filepath.Join(backupPath, fmt.Sprintf("%s_%s.html", templateName, version.Version))
|
|
if err := vm.ExportVersion(templateName, version.Version, backupFile); err != nil {
|
|
vm.logger.Warn("failed to backup version", "template", templateName, "version", version.Version, "error", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
vm.logger.Info("all templates backed up", "backup_path", backupPath)
|
|
return nil
|
|
}
|
|
|
|
// RestoreFromBackup restores templates from a backup
|
|
func (vm *VersionManager) RestoreFromBackup(backupPath string) error {
|
|
return filepath.Walk(backupPath, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !info.IsDir() && filepath.Ext(path) == ".html" {
|
|
filename := info.Name()
|
|
// Parse template name and version from filename
|
|
// This is a simplified implementation - ignore filename
|
|
_ = filename
|
|
return nil
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// GetDiskUsage returns disk usage statistics
|
|
func (vm *VersionManager) GetDiskUsage() (int64, error) {
|
|
var totalSize int64
|
|
|
|
versionsDir := filepath.Join(vm.basePath, "versions")
|
|
if _, err := os.Stat(versionsDir); os.IsNotExist(err) {
|
|
return 0, nil
|
|
}
|
|
|
|
err := filepath.Walk(versionsDir, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !info.IsDir() {
|
|
totalSize += info.Size()
|
|
}
|
|
return nil
|
|
})
|
|
|
|
return totalSize, err
|
|
}
|
|
|
|
// CleanupStorage removes empty directories and orphaned files
|
|
func (vm *VersionManager) CleanupStorage() error {
|
|
versionsDir := filepath.Join(vm.basePath, "versions")
|
|
|
|
return filepath.Walk(versionsDir, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if info.IsDir() {
|
|
// Remove empty directories
|
|
files, err := os.ReadDir(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(files) == 0 && path != versionsDir {
|
|
return os.Remove(path)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
// GetHealth returns the health status of the version manager
|
|
func (vm *VersionManager) GetHealth() map[string]interface{} {
|
|
diskUsage, _ := vm.GetDiskUsage()
|
|
|
|
return map[string]interface{}{
|
|
"status": "healthy",
|
|
"disk_usage": diskUsage,
|
|
"total_templates": len(vm.versions),
|
|
"storage_path": vm.GetStoragePath(""),
|
|
}
|
|
}
|
|
|
|
// ValidateTemplateContent validates template content
|
|
func (vm *VersionManager) ValidateTemplateContent(content []byte) error {
|
|
// Basic validation - check for empty content
|
|
if len(content) == 0 {
|
|
return fmt.Errorf("template content is empty")
|
|
}
|
|
|
|
// Add more validation as needed
|
|
return nil
|
|
}
|
|
|
|
// GetVersionDiff returns differences between two versions
|
|
func (vm *VersionManager) GetVersionDiff(templateName, version1, version2 string) (string, error) {
|
|
// This could be implemented to show differences between versions
|
|
// For now, return a placeholder
|
|
return "Version diff not implemented", nil
|
|
}
|
|
|
|
// SetRetentionPolicy sets the retention policy for versions
|
|
func (vm *VersionManager) SetRetentionPolicy(templateName string, maxVersions int) error {
|
|
return vm.CleanupOldVersions(templateName, maxVersions)
|
|
}
|
|
|
|
// GetRetentionPolicy returns the retention policy for a template
|
|
func (vm *VersionManager) GetRetentionPolicy(templateName string) int {
|
|
// Default retention policy
|
|
return 10
|
|
}
|
|
|
|
// PurgeAllVersions removes all versions for a template
|
|
func (vm *VersionManager) PurgeAllVersions(templateName string) error {
|
|
storagePath := vm.GetStoragePath(templateName)
|
|
if err := os.RemoveAll(storagePath); err != nil {
|
|
return fmt.Errorf("failed to purge versions: %w", err)
|
|
}
|
|
|
|
delete(vm.versions, templateName)
|
|
vm.logger.Info("all versions purged", "template", templateName)
|
|
return nil
|
|
}
|
|
|
|
// CloneTemplate creates a copy of a template with a new name
|
|
func (vm *VersionManager) CloneTemplate(sourceTemplate, newTemplate, description, author string) error {
|
|
versions := vm.versions[sourceTemplate]
|
|
if len(versions) == 0 {
|
|
return fmt.Errorf("source template not found: %s", sourceTemplate)
|
|
}
|
|
|
|
// Get the latest version
|
|
latestVersion := versions[len(versions)-1]
|
|
|
|
// Read the latest version content
|
|
content, err := os.ReadFile(latestVersion.FilePath)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read source template: %w", err)
|
|
}
|
|
|
|
// Save as new template
|
|
newTemplatePath := filepath.Join(vm.basePath, newTemplate+".html")
|
|
if err := os.WriteFile(newTemplatePath, content, 0644); err != nil {
|
|
return fmt.Errorf("failed to create new template: %w", err)
|
|
}
|
|
|
|
return vm.SaveVersion(newTemplate, newTemplatePath, description, author)
|
|
}
|
|
|
|
// GetTemplateUsage returns usage statistics for templates
|
|
func (vm *VersionManager) GetTemplateUsage() map[string]interface{} {
|
|
usage := make(map[string]interface{})
|
|
|
|
for templateName := range vm.versions {
|
|
stats := vm.GetTemplateStats(templateName)
|
|
usage[templateName] = stats
|
|
}
|
|
|
|
return usage
|
|
}
|
|
|
|
// OptimizeStorage optimizes storage by compressing old versions
|
|
func (vm *VersionManager) OptimizeStorage() error {
|
|
// This could be implemented to compress old versions
|
|
// For now, just log the operation
|
|
vm.logger.Info("storage optimization started")
|
|
return nil
|
|
}
|
|
|
|
// GetTemplateInfo returns detailed information about a template
|
|
func (vm *VersionManager) GetTemplateInfo(templateName string) (map[string]interface{}, error) {
|
|
versions := vm.versions[templateName]
|
|
if len(versions) == 0 {
|
|
return nil, fmt.Errorf("template not found: %s", templateName)
|
|
}
|
|
|
|
history, _ := vm.GetVersionHistory(templateName)
|
|
stats := vm.GetTemplateStats(templateName)
|
|
diskUsage, _ := vm.GetDiskUsage()
|
|
|
|
return map[string]interface{}{
|
|
"name": templateName,
|
|
"stats": stats,
|
|
"history": history,
|
|
"disk_usage": diskUsage,
|
|
"storage_path": vm.GetStoragePath(templateName),
|
|
"retention": vm.GetRetentionPolicy(templateName),
|
|
}, nil
|
|
}
|
|
|
|
// ExportTemplateMetadata exports template metadata to a file
|
|
func (vm *VersionManager) ExportTemplateMetadata(exportPath string) error {
|
|
// This could be implemented to export metadata
|
|
// For now, just log the operation
|
|
vm.logger.Info("template metadata export started", "export_path", exportPath)
|
|
return nil
|
|
}
|
|
|
|
// ImportTemplateMetadata imports template metadata from a file
|
|
func (vm *VersionManager) ImportTemplateMetadata(importPath string) error {
|
|
// This could be implemented to import metadata
|
|
// For now, just log the operation
|
|
vm.logger.Info("template metadata import started", "import_path", importPath)
|
|
return nil
|
|
}
|
|
|
|
// ValidateTemplateName validates a template name
|
|
func (vm *VersionManager) ValidateTemplateName(name string) error {
|
|
if name == "" {
|
|
return fmt.Errorf("template name cannot be empty")
|
|
}
|
|
|
|
if len(name) > 50 {
|
|
return fmt.Errorf("template name too long")
|
|
}
|
|
|
|
// Check for invalid characters
|
|
invalidChars := []string{"/", "\\", ":", "*", "?", "\"", "<", ">", "|"}
|
|
for _, char := range invalidChars {
|
|
if containsString(name, char) {
|
|
return fmt.Errorf("template name contains invalid character: %s", char)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Helper function to check if string contains substring
|
|
func containsString(s, substr string) bool {
|
|
for _, char := range substr {
|
|
for _, c := range s {
|
|
if c == char {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// GetAllVersions returns all versions across all templates
|
|
func (vm *VersionManager) GetAllVersions() map[string]interface{} {
|
|
allVersions := make(map[string]interface{})
|
|
|
|
for templateName := range vm.versions {
|
|
allVersions[templateName] = vm.versions[templateName]
|
|
}
|
|
|
|
return allVersions
|
|
}
|
|
|
|
// SearchVersions searches for versions matching criteria
|
|
func (vm *VersionManager) SearchVersions(criteria map[string]interface{}) []VersionInfo {
|
|
var results []VersionInfo
|
|
|
|
for templateName := range vm.versions {
|
|
versions := vm.versions[templateName]
|
|
for _, version := range versions {
|
|
if vm.matchesCriteria(version, criteria) {
|
|
results = append(results, version)
|
|
}
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// matchesCriteria checks if a version matches search criteria
|
|
func (vm *VersionManager) matchesCriteria(version VersionInfo, criteria map[string]interface{}) bool {
|
|
for key, value := range criteria {
|
|
switch key {
|
|
case "author":
|
|
if version.Author != value.(string) {
|
|
return false
|
|
}
|
|
case "before":
|
|
if !version.Timestamp.Before(value.(time.Time)) {
|
|
return false
|
|
}
|
|
case "after":
|
|
if !version.Timestamp.After(value.(time.Time)) {
|
|
return false
|
|
}
|
|
case "description_contains":
|
|
if !containsString(version.Description, value.(string)) {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// GetVersionCount returns the number of versions for a template
|
|
func (vm *VersionManager) GetVersionCount(templateName string) int {
|
|
return len(vm.versions[templateName])
|
|
}
|
|
|
|
// GetOldestVersion returns the oldest version for a template
|
|
func (vm *VersionManager) GetOldestVersion(templateName string) (*VersionInfo, error) {
|
|
versions := vm.versions[templateName]
|
|
if len(versions) == 0 {
|
|
return nil, fmt.Errorf("no versions found for template: %s", templateName)
|
|
}
|
|
return &versions[0], nil
|
|
}
|
|
|
|
// GetNewestVersion returns the newest version for a template
|
|
func (vm *VersionManager) GetNewestVersion(templateName string) (*VersionInfo, error) {
|
|
versions := vm.versions[templateName]
|
|
if len(versions) == 0 {
|
|
return nil, fmt.Errorf("no versions found for template: %s", templateName)
|
|
}
|
|
return &versions[len(versions)-1], nil
|
|
}
|
|
|
|
// GetActiveVersion returns the active version for a template
|
|
func (vm *VersionManager) GetActiveVersion(templateName string) (*VersionInfo, error) {
|
|
versions := vm.versions[templateName]
|
|
for _, v := range versions {
|
|
if v.Active {
|
|
return &v, nil
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("no active version found for template: %s", templateName)
|
|
}
|
|
|
|
// SetActiveVersion sets a specific version as active
|
|
func (vm *VersionManager) SetActiveVersion(templateName, version string) error {
|
|
versions := vm.versions[templateName]
|
|
for i := range versions {
|
|
versions[i].Active = versions[i].Version == version
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetVersionByHash returns a version by its hash
|
|
func (vm *VersionManager) GetVersionByHash(templateName, hash string) (*VersionInfo, error) {
|
|
versions := vm.versions[templateName]
|
|
for _, v := range versions {
|
|
if v.Hash == hash {
|
|
return &v, nil
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("version with hash %s not found for template %s", hash, templateName)
|
|
}
|
|
|
|
// GetVersionsByDateRange returns versions within a date range
|
|
func (vm *VersionManager) GetVersionsByDateRange(templateName string, start, end time.Time) []VersionInfo {
|
|
versions := vm.versions[templateName]
|
|
var results []VersionInfo
|
|
|
|
for _, version := range versions {
|
|
if version.Timestamp.After(start) && version.Timestamp.Before(end) {
|
|
results = append(results, version)
|
|
}
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
|
|
// GetTemplateUsageStats returns usage statistics for templates
|
|
func (vm *VersionManager) GetTemplateUsageStats() map[string]interface{} {
|
|
stats := make(map[string]interface{})
|
|
|
|
totalVersions := 0
|
|
totalSize := int64(0)
|
|
|
|
for templateName, versions := range vm.versions {
|
|
for _, v := range versions {
|
|
totalVersions++
|
|
totalSize += v.Size
|
|
}
|
|
|
|
stats[templateName] = map[string]interface{}{
|
|
"versions": len(versions),
|
|
"size": totalSize,
|
|
}
|
|
}
|
|
|
|
stats["total_templates"] = len(vm.versions)
|
|
stats["total_versions"] = totalVersions
|
|
stats["total_size"] = totalSize
|
|
|
|
return stats
|
|
}
|
|
|
|
// ArchiveTemplate archives a template and all its versions
|
|
func (vm *VersionManager) ArchiveTemplate(templateName string) error {
|
|
// This could be implemented to archive templates
|
|
// For now, just log the operation
|
|
vm.logger.Info("template archived", "template", templateName)
|
|
return nil
|
|
}
|
|
|
|
// RestoreTemplate restores an archived template
|
|
func (vm *VersionManager) RestoreTemplate(templateName string) error {
|
|
// This could be implemented to restore templates
|
|
// For now, just log the operation
|
|
vm.logger.Info("template restored", "template", templateName)
|
|
return nil
|
|
}
|
|
|
|
// GetTemplateBackup creates a backup of all template versions
|
|
func (vm *VersionManager) GetTemplateBackup() (*VersionHistory, error) {
|
|
// This is a placeholder for backup functionality
|
|
return nil, nil
|
|
}
|
|
|
|
// SetVersionLabel sets a label for a specific version
|
|
func (vm *VersionManager) SetVersionLabel(templateName, version, label string) error {
|
|
// This could be implemented to add labels to versions
|
|
vm.logger.Info("version label set", "template", templateName, "version", version, "label", label)
|
|
return nil
|
|
}
|
|
|
|
// GetVersionLabel returns the label for a specific version
|
|
func (vm *VersionManager) GetVersionLabel(templateName, version string) string {
|
|
// This could be implemented to get labels from versions
|
|
return ""
|
|
}
|
|
|
|
// GetVersionTags returns tags for a specific version
|
|
func (vm *VersionManager) GetVersionTags(templateName, version string) []string {
|
|
// This could be implemented to get tags from versions
|
|
return []string{}
|
|
}
|
|
|
|
// AddVersionTag adds a tag to a specific version
|
|
func (vm *VersionManager) AddVersionTag(templateName, version, tag string) error {
|
|
// This could be implemented to add tags to versions
|
|
vm.logger.Info("version tag added", "template", templateName, "version", version, "tag", tag)
|
|
return nil
|
|
}
|
|
|
|
// RemoveVersionTag removes a tag from a specific version
|
|
func (vm *VersionManager) RemoveVersionTag(templateName, version, tag string) error {
|
|
// This could be implemented to remove tags from versions
|
|
vm.logger.Info("version tag removed", "template", templateName, "version", version, "tag", tag)
|
|
return nil
|
|
}
|
|
|
|
// GetVersionComments returns comments for a specific version
|
|
func (vm *VersionManager) GetVersionComments(templateName, version string) []string {
|
|
// This could be implemented to get comments from versions
|
|
return []string{}
|
|
}
|
|
|
|
// AddVersionComment adds a comment to a specific version
|
|
func (vm *VersionManager) AddVersionComment(templateName, version, comment string) error {
|
|
// This could be implemented to add comments to versions
|
|
vm.logger.Info("version comment added", "template", templateName, "version", version, "comment", comment)
|
|
return nil
|
|
}
|
|
|
|
// RemoveVersionComment removes a comment from a specific version
|
|
func (vm *VersionManager) RemoveVersionComment(templateName, version, comment string) error {
|
|
// This could be implemented to remove comments from versions
|
|
vm.logger.Info("version comment removed", "template", templateName, "version", version, "comment", comment)
|
|
return nil
|
|
}
|
|
|
|
// GetVersionAuthor returns the author of a specific version
|
|
func (vm *VersionManager) GetVersionAuthor(templateName, version string) string {
|
|
versions := vm.versions[templateName]
|
|
for _, v := range versions {
|
|
if v.Version == version {
|
|
return v.Author
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetVersionDescription returns the description of a specific version
|
|
func (vm *VersionManager) GetVersionDescription(templateName, version string) string {
|
|
versions := vm.versions[templateName]
|
|
for _, v := range versions {
|
|
if v.Version == version {
|
|
return v.Description
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// GetVersionTimestamp returns the timestamp of a specific version
|
|
func (vm *VersionManager) GetVersionTimestamp(templateName, version string) (time.Time, error) {
|
|
versions := vm.versions[templateName]
|
|
for _, v := range versions {
|
|
if v.Version == version {
|
|
return v.Timestamp, nil
|
|
}
|
|
}
|
|
return time.Time{}, fmt.Errorf("version %s not found for template %s", version, templateName)
|
|
}
|
|
|
|
// GetVersionFilePath returns the file path of a specific version
|
|
func (vm *VersionManager) GetVersionFilePath(templateName, version string) (string, error) {
|
|
versions := vm.versions[templateName]
|
|
for _, v := range versions {
|
|
if v.Version == version {
|
|
return v.FilePath, nil
|
|
}
|
|
}
|
|
return "", fmt.Errorf("version %s not found for template %s", version, templateName)
|
|
}
|
|
|
|
// GetVersionSize returns the size of a specific version
|
|
func (vm *VersionManager) GetVersionSize(templateName, version string) (int64, error) {
|
|
versions := vm.versions[templateName]
|
|
for _, v := range versions {
|
|
if v.Version == version {
|
|
return v.Size, nil
|
|
}
|
|
}
|
|
return 0, fmt.Errorf("version %s not found for template %s", version, templateName)
|
|
}
|
|
|
|
// GetVersionHash returns the hash of a specific version
|
|
func (vm *VersionManager) GetVersionHash(templateName, version string) (string, error) {
|
|
versions := vm.versions[templateName]
|
|
for _, v := range versions {
|
|
if v.Version == version {
|
|
return v.Hash, nil
|
|
}
|
|
}
|
|
return "", fmt.Errorf("version %s not found for template %s", version, templateName)
|
|
}
|
|
|
|
// IsVersionActive returns whether a specific version is active
|
|
func (vm *VersionManager) IsVersionActive(templateName, version string) (bool, error) {
|
|
versions := vm.versions[templateName]
|
|
for _, v := range versions {
|
|
if v.Version == version {
|
|
return v.Active, nil
|
|
}
|
|
}
|
|
return false, fmt.Errorf("version %s not found for template %s", version, templateName)
|
|
}
|
|
|
|
|
|
// GetTotalDiskUsage returns the total disk usage across all templates
|
|
func (vm *VersionManager) GetTotalDiskUsage() int64 {
|
|
total := int64(0)
|
|
for _, versions := range vm.versions {
|
|
for _, v := range versions {
|
|
total += v.Size
|
|
}
|
|
}
|
|
return total
|
|
}
|
|
|
|
// GetVersionSummary returns a summary of all versions
|
|
func (vm *VersionManager) GetVersionSummary() map[string]interface{} {
|
|
summary := map[string]interface{}{
|
|
"total_templates": len(vm.versions),
|
|
"total_versions": vm.getTotalVersionCount(),
|
|
"total_size": vm.GetTotalDiskUsage(),
|
|
"templates": make(map[string]int),
|
|
}
|
|
|
|
for templateName, versions := range vm.versions {
|
|
summary["templates"].(map[string]int)[templateName] = len(versions)
|
|
}
|
|
|
|
return summary
|
|
}
|
|
|
|
// getTotalVersionCount returns the total number of versions across all templates
|
|
func (vm *VersionManager) getTotalVersionCount() int {
|
|
count := 0
|
|
for _, versions := range vm.versions {
|
|
count += len(versions)
|
|
}
|
|
return count
|
|
}
|
|
|
|
// GetVersionHistorySummary returns a summary of version history
|
|
func (vm *VersionManager) GetVersionHistorySummary(templateName string) map[string]interface{} {
|
|
versions := vm.versions[templateName]
|
|
if len(versions) == 0 {
|
|
return map[string]interface{}{
|
|
"template_name": templateName,
|
|
"total_versions": 0,
|
|
"current_version": "",
|
|
"oldest_version": "",
|
|
"newest_version": "",
|
|
}
|
|
}
|
|
|
|
return map[string]interface{}{
|
|
"template_name": templateName,
|
|
"total_versions": len(versions),
|
|
"current_version": versions[len(versions)-1].Version,
|
|
"oldest_version": versions[0].Version,
|
|
"newest_version": versions[len(versions)-1].Version,
|
|
"first_created": versions[0].Timestamp,
|
|
"last_updated": versions[len(versions)-1].Timestamp,
|
|
"total_size": func() int64 {
|
|
total := int64(0)
|
|
for _, v := range versions {
|
|
total += v.Size
|
|
}
|
|
return total
|
|
}(),
|
|
}
|
|
}
|
|
|
|
// GetTemplateVersionHistory returns the complete version history for a template
|
|
func (vm *VersionManager) GetTemplateVersionHistory(templateName string) (*VersionHistory, error) {
|
|
versions := vm.versions[templateName]
|
|
if len(versions) == 0 {
|
|
return nil, fmt.Errorf("no versions found for template: %s", templateName)
|
|
}
|
|
|
|
var current VersionInfo
|
|
for _, v := range versions {
|
|
if v.Active {
|
|
current = v
|
|
break
|
|
}
|
|
}
|
|
|
|
// If no active version, use the latest
|
|
if current.Version == "" {
|
|
current = versions[len(versions)-1]
|
|
}
|
|
|
|
return &VersionHistory{
|
|
TemplateName: templateName,
|
|
Versions: versions,
|
|
Current: current,
|
|
}, nil
|
|
} |