|
package main |
|
|
|
import ( |
|
"fmt" |
|
"os" |
|
"path/filepath" |
|
"time" |
|
) |
|
|
|
const ( |
|
dailyDir = "backups/daily" |
|
weeklyDir = "backups/weekly" |
|
monthlyDir = "backups/monthly" |
|
dailyExpire = 72 * time.Hour |
|
weeklyExpire = 90 * 24 * time.Hour |
|
) |
|
|
|
func main() { |
|
currentDay := time.Now() |
|
weeklyCutoff := currentDay.Add(-weeklyExpire) |
|
|
|
// Process daily backups |
|
err := processDailyBackups(currentDay, weeklyCutoff) |
|
if err != nil { |
|
fmt.Println("Error processing daily backups:", err) |
|
} |
|
|
|
// Process weekly backups |
|
err = processWeeklyBackups(currentDay) |
|
if err != nil { |
|
fmt.Println("Error processing weekly backups:", err) |
|
} |
|
} |
|
|
|
func processDailyBackups(currentDay, weeklyCutoff time.Time) error { |
|
files, err := ioutilReadDir(dailyDir) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
for _, file := range files { |
|
if file.IsDir() { |
|
continue |
|
} |
|
|
|
modifiedTime := file.ModTime() |
|
age := currentDay.Sub(modifiedTime) |
|
|
|
if age < dailyExpire { |
|
// Leave the file in place if it's less than 72 hours old |
|
continue |
|
} |
|
|
|
weekNumber := int(currentDay.YearDay()/7) + 1 |
|
weeklyBackupDir := filepath.Join(weeklyDir, fmt.Sprintf("week%d", weekNumber)) |
|
|
|
if _, err := os.Stat(weeklyBackupDir); os.IsNotExist(err) { |
|
// Move to the weekly folder if a backup for that week does not exist |
|
os.MkdirAll(weeklyBackupDir, os.ModePerm) |
|
err := os.Rename(filepath.Join(dailyDir, file.Name()), filepath.Join(weeklyBackupDir, file.Name())) |
|
if err != nil { |
|
fmt.Printf("Error moving %s to weekly: %v\n", file.Name(), err) |
|
} |
|
} else { |
|
// Delete the file if it's older than 72 hours and a weekly backup already exists |
|
err := os.Remove(filepath.Join(dailyDir, file.Name())) |
|
if err != nil { |
|
fmt.Printf("Error deleting %s: %v\n", file.Name(), err) |
|
} |
|
} |
|
} |
|
return nil |
|
} |
|
|
|
func processWeeklyBackups(currentDay time.Time) error { |
|
files, err := ioutilReadDir(weeklyDir) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
for _, file := range files { |
|
if file.IsDir() { |
|
continue |
|
} |
|
|
|
modifiedTime := file.ModTime() |
|
age := currentDay.Sub(modifiedTime) |
|
|
|
if age < weeklyExpire { |
|
// Leave it in place if it's less than 90 days old or belongs to the week 90 days ago |
|
continue |
|
} |
|
|
|
year := modifiedTime.Year() |
|
monthlyYearDir := filepath.Join(monthlyDir, fmt.Sprintf("%d", year)) |
|
os.MkdirAll(monthlyYearDir, os.ModePerm) |
|
|
|
monthlyBackupFile := filepath.Join(monthlyYearDir, file.Name()) |
|
|
|
if _, err := os.Stat(monthlyBackupFile); os.IsNotExist(err) { |
|
// Move to the monthly/{year}/ directory if a monthly backup for that year does not already exist |
|
err := os.Rename(filepath.Join(weeklyDir, file.Name()), monthlyBackupFile) |
|
if err != nil { |
|
fmt.Printf("Error moving %s to monthly: %v\n", file.Name(), err) |
|
} |
|
} else { |
|
// Delete the file if it's older than 90 days and a monthly backup already exists |
|
err := os.Remove(filepath.Join(weeklyDir, file.Name())) |
|
if err != nil { |
|
fmt.Printf("Error deleting %s: %v\n", file.Name(), err) |
|
} |
|
} |
|
} |
|
return nil |
|
} |
|
|
|
func ioutilReadDir(dirPath string) ([]os.FileInfo, error) { |
|
files, err := os.ReadDir(dirPath) |
|
if err != nil { |
|
return nil, err |
|
} |
|
var result []os.FileInfo |
|
for _, file := range files { |
|
result = append(result, file) |
|
} |
|
return result, nil |
|
} |