Class: Aidp::Setup::Devcontainer::BackupManager

Inherits:
Object
  • Object
show all
Defined in:
lib/aidp/setup/devcontainer/backup_manager.rb

Overview

Manages backups of devcontainer.json before modifications

Defined Under Namespace

Classes: BackupError

Instance Method Summary collapse

Constructor Details

#initialize(project_dir, clock: Time) ⇒ BackupManager

Returns a new instance of BackupManager.



13
14
15
16
17
# File 'lib/aidp/setup/devcontainer/backup_manager.rb', line 13

def initialize(project_dir, clock: Time)
  @project_dir = project_dir
  @backup_dir = File.join(project_dir, ".aidp", "backups", "devcontainer")
  @clock = clock
end

Instance Method Details

#cleanup_old_backups(keep_count = 10) ⇒ Integer

Delete old backups, keeping only the N most recent

Parameters:

  • keep_count (Integer) (defaults to: 10)

    Number of backups to keep

Returns:

  • (Integer)

    Number of backups deleted



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/aidp/setup/devcontainer/backup_manager.rb', line 96

def cleanup_old_backups(keep_count = 10)
  backups = list_backups
  return 0 if backups.size <= keep_count

  to_delete = backups[keep_count..]
  deleted_count = 0

  to_delete.each do |backup|
    File.delete(backup[:path]) if File.exist?(backup[:path])

     = "#{backup[:path]}.meta"
    File.delete() if File.exist?()

    deleted_count += 1
  end

  Aidp.log_info("backup_manager", "cleaned up old backups",
    deleted: deleted_count,
    kept: keep_count)

  deleted_count
end

#create_backup(source_path, metadata = {}) ⇒ String

Create a backup of the devcontainer file

Parameters:

  • source_path (String)

    Path to devcontainer.json to backup

  • metadata (Hash) (defaults to: {})

    Optional metadata to store with backup

Returns:

  • (String)

    Path to backup file



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/aidp/setup/devcontainer/backup_manager.rb', line 23

def create_backup(source_path,  = {})
  unless File.exist?(source_path)
    raise BackupError, "Source file does not exist: #{source_path}"
  end

  ensure_backup_directory_exists

  timestamp = current_time.utc.strftime("%Y%m%d_%H%M%S")
  backup_filename = "devcontainer-#{timestamp}.json"
  backup_path = File.join(@backup_dir, backup_filename)

  FileUtils.cp(source_path, backup_path)

  # Create metadata file
  if .any?
     = "#{backup_path}.meta"
    File.write(, JSON.pretty_generate())
  end

  Aidp.log_info("backup_manager", "created backup",
    source: source_path,
    backup: backup_path)

  backup_path
rescue => e
  raise BackupError, "Failed to create backup: #{e.message}"
end

#latest_backupHash?

Get the most recent backup

Returns:

  • (Hash, nil)

    Backup info or nil if no backups



121
122
123
# File 'lib/aidp/setup/devcontainer/backup_manager.rb', line 121

def latest_backup
  list_backups.first
end

#list_backupsArray<Hash>

List all available backups

Returns:

  • (Array<Hash>)

    Array of backup info hashes



53
54
55
56
57
58
59
60
61
# File 'lib/aidp/setup/devcontainer/backup_manager.rb', line 53

def list_backups
  return [] unless File.directory?(@backup_dir)

  Dir.glob(File.join(@backup_dir, "devcontainer-*.json"))
    .reject { |f| f.end_with?(".meta") }
    .map { |path| backup_info(path) }
    .sort_by { |info| info[:timestamp] }
    .reverse
end

#restore_backup(backup_path, target_path, create_backup: true) ⇒ Boolean

Restore a backup to the specified location

Parameters:

  • backup_path (String)

    Path to backup file

  • target_path (String)

    Where to restore the backup

  • create_backup (Boolean) (defaults to: true)

    Create backup of target before restoring

Returns:

  • (Boolean)

    true if successful



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/aidp/setup/devcontainer/backup_manager.rb', line 68

def restore_backup(backup_path, target_path, create_backup: true)
  unless File.exist?(backup_path)
    raise BackupError, "Backup file does not exist: #{backup_path}"
  end

  # Backup current file before restoring
  if create_backup && File.exist?(target_path)
    create_backup(target_path, {
      reason: "pre_restore",
      restoring_from: backup_path
    })
  end

  FileUtils.mkdir_p(File.dirname(target_path))
  FileUtils.cp(backup_path, target_path)

  Aidp.log_info("backup_manager", "restored backup",
    backup: backup_path,
    target: target_path)

  true
rescue => e
  raise BackupError, "Failed to restore backup: #{e.message}"
end

#total_backup_sizeInteger

Calculate total size of all backups

Returns:

  • (Integer)

    Total size in bytes



127
128
129
130
131
132
# File 'lib/aidp/setup/devcontainer/backup_manager.rb', line 127

def total_backup_size
  return 0 unless File.directory?(@backup_dir)

  Dir.glob(File.join(@backup_dir, "devcontainer-*.{json,meta}"))
    .sum { |f| File.size(f) }
end