Skip to content

Commit 50bd4ab

Browse files
committed
feat: implement option for using realtive paths
fixes #11
1 parent 009e7b9 commit 50bd4ab

2 files changed

Lines changed: 94 additions & 48 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ The name of your backup is the key at root level. Starting from there you can co
114114
| archive_type | string | No | `tar.gz` | The type of archive to be used (`tar.gz` or `zip` are valid options) |
115115
| add_subfolder | boolean | No | `false` | Creates a new subfolder in `<destination>` for this unit if set to true |
116116
| enabled | boolean | No | `true` | Switch to disable each unit individually |
117+
| use_absolute_paths | boolean | No | `true` | Uses absolute file paths in the archive (see [#11](https://github.com/d-Rickyy-b/backmeup/issues/11)) |
117118

118119
Be careful when using quotes in paths. For most strings you don't even need to use quotes at all. When using double quotes (`"`), you must escape backslashes (`\`) when you want to use them as literal characters (such as in Windows paths).
119120
Check [this handy article](https://www.yaml.info/learn/quote.html) for learning more about quotes in yaml.

main.go

Lines changed: 93 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,38 @@ var VERBOSE bool
2323
var DEBUG bool
2424

2525
type Unit struct {
26-
name string
27-
sources []string
28-
destination string
29-
excludes []string
30-
archiveType string
31-
addSubfolder bool
32-
enabled bool
26+
name string
27+
sources []string
28+
destination string
29+
excludes []string
30+
archiveType string
31+
addSubfolder bool
32+
enabled bool
33+
useAbsolutePaths bool
3334
}
3435

3536
type Config struct {
3637
units []Unit
3738
}
3839

40+
type BackupFileMetadata struct {
41+
path string
42+
backupBasePath string
43+
}
44+
3945
func (config Config) FromYaml(yamlData []byte) (Config, error) {
4046
// Create a config object from yaml byte array
4147
log.Println("Parsing config yaml")
4248

4349
// Helper struct for parsing the yaml
4450
type YamlUnit struct {
45-
Sources *[]string `yaml:"sources"`
46-
Destination *string `yaml:"destination"`
47-
Excludes *[]string `yaml:"excludes"`
48-
ArchiveType *string `yaml:"archive_type"`
49-
AddSubfolder *bool `yaml:"add_subfolder"`
50-
Enabled *bool `yaml:"enabled"`
51+
Sources *[]string `yaml:"sources"`
52+
Destination *string `yaml:"destination"`
53+
Excludes *[]string `yaml:"excludes"`
54+
ArchiveType *string `yaml:"archive_type"`
55+
AddSubfolder *bool `yaml:"add_subfolder"`
56+
Enabled *bool `yaml:"enabled"`
57+
UseAbsolutePaths *bool `yaml:"use_absolute_paths"`
5158
}
5259

5360
// Sample yaml config:
@@ -97,6 +104,11 @@ func (config Config) FromYaml(yamlData []byte) (Config, error) {
97104
unit.excludes = *yamlUnit.Excludes
98105
}
99106

107+
unit.useAbsolutePaths = true
108+
if yamlUnit.UseAbsolutePaths != nil {
109+
unit.useAbsolutePaths = *yamlUnit.UseAbsolutePaths
110+
}
111+
100112
if yamlUnit.Sources == nil || yamlUnit.Destination == nil {
101113
log.Fatalf("Sources or destination can't be parsed for unit '%s'", unitName)
102114
} else {
@@ -147,9 +159,9 @@ func handleExcludes(path string, excludes []string) bool {
147159
return false
148160
}
149161

150-
func getFiles(sourcePath string, excludes []string) ([]string, error) {
162+
func getFiles(sourcePath string, excludes []string) ([]BackupFileMetadata, error) {
151163
// Returns all file paths recursively within a certain source directory
152-
var pathsToBackup []string
164+
var pathsToBackup []BackupFileMetadata
153165

154166
_, statErr := os.Stat(sourcePath)
155167
if statErr != nil {
@@ -174,7 +186,11 @@ func getFiles(sourcePath string, excludes []string) ([]string, error) {
174186
return nil
175187
}
176188

177-
pathsToBackup = append(pathsToBackup, path)
189+
fileMetadata := BackupFileMetadata{
190+
path: path,
191+
backupBasePath: sourcePath,
192+
}
193+
pathsToBackup = append(pathsToBackup, fileMetadata)
178194
return nil
179195
})
180196
if err != nil {
@@ -200,50 +216,86 @@ func validatePath(path string, mustBeDir bool) bool {
200216
return true
201217
}
202218

203-
func writeTar(backupArchivePath string, filesToBackup []string) {
204-
file, err := os.Create(backupArchivePath)
219+
func getPathInArchive(filePath string, backupBasePath string, unit Unit) string {
220+
// Remove the base path from the file path within the archive, if option is set
221+
pathInArchive := filePath
222+
if !unit.useAbsolutePaths {
223+
parentBasePath := filepath.Dir(backupBasePath)
224+
pathInArchive = strings.ReplaceAll(filePath, parentBasePath, "")
225+
226+
if strings.HasPrefix(pathInArchive, "\\") {
227+
pathInArchive = pathInArchive[1:]
228+
}
229+
}
230+
return pathInArchive
231+
}
232+
233+
func writeArchive(backupArchivePath string, filesToBackup []BackupFileMetadata, unit Unit) {
234+
archiveFile, err := os.Create(backupArchivePath)
205235
if err != nil {
206236
log.Fatalln(err)
207237
}
208-
defer file.Close()
209-
// set up the gzip writer
210-
gw := gzip.NewWriter(file)
238+
defer archiveFile.Close()
239+
240+
switch unit.archiveType {
241+
case "tar.gz":
242+
writeTar(archiveFile, filesToBackup, unit)
243+
case "zip":
244+
writeZip(archiveFile, filesToBackup, unit)
245+
default:
246+
log.Fatalf("Can't handle archive type '%s'", unit.archiveType)
247+
}
248+
}
249+
250+
func writeTar(archiveFile *os.File, filesToBackup []BackupFileMetadata, unit Unit) {
251+
// set up the gzip and tar writer
252+
gw := gzip.NewWriter(archiveFile)
211253
defer gw.Close()
212254
tw := tar.NewWriter(gw)
213255
defer tw.Close()
214256

257+
// Init progress bar
215258
bar := pb.StartNew(len(filesToBackup))
216259
for i := range filesToBackup {
217-
if err := addFileToTar(tw, filesToBackup[i]); err != nil {
260+
fileMetadata := filesToBackup[i]
261+
filePath := fileMetadata.path
262+
263+
pathInArchive := getPathInArchive(filePath, fileMetadata.backupBasePath, unit)
264+
265+
if err := addFileToTar(tw, filePath, pathInArchive); err != nil {
218266
log.Fatalln(err)
219267
}
220268
bar.Increment()
221269
}
222270
bar.Finish()
223271
}
224272

225-
func writeZip(backupArchivePath string, filesToBackup []string) {
226-
file, err := os.Create(backupArchivePath)
227-
if err != nil {
228-
log.Fatalln(err)
229-
}
230-
defer file.Close()
231-
zw := zip.NewWriter(file)
273+
func writeZip(archiveFile *os.File, filesToBackup []BackupFileMetadata, unit Unit) {
274+
zw := zip.NewWriter(archiveFile)
232275
defer zw.Close()
233276

277+
bar := pb.StartNew(len(filesToBackup))
234278
for i := range filesToBackup {
235-
if err := addFileToZip(zw, filesToBackup[i]); err != nil {
279+
fileMetadata := filesToBackup[i]
280+
filePath := fileMetadata.path
281+
282+
pathInArchive := getPathInArchive(filePath, fileMetadata.backupBasePath, unit)
283+
284+
if err := addFileToZip(zw, filePath, pathInArchive); err != nil {
236285
log.Fatalln(err)
237286
}
287+
bar.Increment()
238288
}
289+
bar.Finish()
239290
}
240291

241-
func writeBackup(filesToBackup []string, backupBasePath string, unitName string, fileExt string, addSubfolder bool) {
292+
func writeBackup(filesToBackup []BackupFileMetadata, unit Unit) {
242293
now := time.Now()
243294
timeStamp := now.Format("2006-01-02_15-04")
295+
backupBasePath := unit.destination
244296

245-
if addSubfolder {
246-
newBackupBasePath := filepath.Join(backupBasePath, unitName)
297+
if unit.addSubfolder {
298+
newBackupBasePath := filepath.Join(unit.destination, unit.name)
247299
pathExists := validatePath(newBackupBasePath, true)
248300

249301
if !pathExists {
@@ -256,19 +308,12 @@ func writeBackup(filesToBackup []string, backupBasePath string, unitName string,
256308
backupBasePath = newBackupBasePath
257309
}
258310

259-
backupArchiveName := unitName + "-" + timeStamp + "." + fileExt
311+
backupArchiveName := unit.name + "-" + timeStamp + "." + unit.archiveType
260312
backupArchivePath := filepath.Join(backupBasePath, backupArchiveName)
261313

262314
// TODO check if archive already exists. If yes, append -1 to it and try again
263315

264-
if fileExt == "tar.gz" {
265-
writeTar(backupArchivePath, filesToBackup)
266-
} else if fileExt == "zip" {
267-
writeZip(backupArchivePath, filesToBackup)
268-
} else {
269-
log.Fatalf("Can't handle archive type '%s'", fileExt)
270-
}
271-
316+
writeArchive(backupArchivePath, filesToBackup, unit)
272317
log.Printf("Archive created successfully at '%s'", backupArchivePath)
273318
}
274319

@@ -280,7 +325,7 @@ func backupUnit(unit Unit) {
280325
}
281326

282327
log.Printf("Creating backup for unit '%s'\n", unit.name)
283-
var filesToBackup []string
328+
var filesToBackup []BackupFileMetadata
284329

285330
// Check all source files from the disk in the specified source directories
286331
for _, sourcePath := range unit.sources {
@@ -296,7 +341,7 @@ func backupUnit(unit Unit) {
296341
log.Printf("No files found for sources in unit '%s'. Creating no backup!", unit.name)
297342
return
298343
}
299-
writeBackup(filesToBackup, unit.destination, unit.name, unit.archiveType, unit.addSubfolder)
344+
writeBackup(filesToBackup, unit)
300345
}
301346

302347
func runBackup(config Config) {
@@ -356,7 +401,7 @@ func readConfig(configPath string) (Config, error) {
356401
return c, validateErr
357402
}
358403

359-
func addFileToTar(tw *tar.Writer, path string) error {
404+
func addFileToTar(tw *tar.Writer, path string, pathInArchive string) error {
360405
file, err := os.Open(path)
361406
if err != nil {
362407
return err
@@ -367,7 +412,7 @@ func addFileToTar(tw *tar.Writer, path string) error {
367412
// now lets create the header as needed for this file within the tarball
368413
header := new(tar.Header)
369414
header.Format = tar.FormatGNU
370-
header.Name = path
415+
header.Name = pathInArchive
371416
header.Size = stat.Size()
372417
header.Mode = int64(stat.Mode())
373418
header.ModTime = stat.ModTime()
@@ -383,7 +428,7 @@ func addFileToTar(tw *tar.Writer, path string) error {
383428
return nil
384429
}
385430

386-
func addFileToZip(zw *zip.Writer, path string) error {
431+
func addFileToZip(zw *zip.Writer, path string, pathInArchive string) error {
387432
file, err := os.Open(path)
388433
if err != nil {
389434
return err
@@ -395,7 +440,7 @@ func addFileToZip(zw *zip.Writer, path string) error {
395440
if headerErr != nil {
396441
return headerErr
397442
}
398-
header.Name = path
443+
header.Name = pathInArchive
399444
// write the header to the zip archive
400445
writer, headerErr := zw.CreateHeader(header)
401446
if headerErr != nil {

0 commit comments

Comments
 (0)