-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbackupGenerator.js
196 lines (153 loc) · 5.41 KB
/
backupGenerator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
var AdmZip = require('adm-zip');
var logger = require('./logger.js');
const fs = require('fs.extra');
const path = require('path')
// produces string representation of the date in the following format:
// year-month-day-hour-minute
function getCurrentDateString() {
let date = new Date();
let dateString = "" + date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + "-" +
(date.getHours() + 1) + "-" + (date.getMinutes() + 1);
return dateString;
}
// used to parse the integer value for the day in a datestring,
// for the purposes of determining the age of zip files named with the datestring
function getIntegerDayFromDateString(ds) {
let dashCount = 0;
let dayString = '';
let i = 0
while(i < ds.length) {
if (ds[i] === '-'){
dashCount += 1;
// past the day portion of the string; end
if (dashCount >= 3) {
break;
}
// don't add a dash to the day string
i += 1;
continue;
}
if (dashCount === 2) {
dayString += ds[i];
}
i += 1;
}
return parseInt(dayString);
}
// from https://stackoverflow.com/questions/18112204/get-all-directories-within-directory-nodejs
//
// returns only those entries within srcpath which are themselves directories
function getDirectories (srcpath) {
return fs.readdirSync(srcpath)
.filter(file => fs.lstatSync(path.join(srcpath, file)).isDirectory())
}
// writes contents at ./backups to ./zips/ with name as the file name
// TYPICAL USEAGE: name should be getCurrentDateString()
// we dont simply cal getCurrentDateString here because the function calling this one
// needs the exact name to verify that the zip was created properly
// note -- AdmZip sometimes fails on e.g. image files, but has worked fine on hte tar files which
// this will be used for.
function createZipFromBackupDirectories(name) {
let zip = new AdmZip();
zip.addLocalFolder('./backups/');
zip.writeZip('./zips/' + name);
}
// removes a file specified by path if it is a valid file
// used to filter out those entries sometimes returned by fs.readirSync which arent actually files
function removeFileIfExists(path) {
console.log('checking ' + path);
if (fs.existsSync(path)) {
console.log('removing ' + path);
fs.unlinkSync(path);
}
}
// deletes files found in the subdirectories of ./backups/
function removeUnzippedBackupFiles() {
let backupSubDirectories = getDirectories('./backups/');
for (let i = 0; i < backupSubDirectories.length; i++) {
let subdir = './backups/' + backupSubDirectories[i];
let files = fs.readdirSync(subdir);
for (let j = 0; j < files.length; j++) {
removeFileIfExists(subdir + '/' + files[j]);
}
}
}
// returns true if filename ends with '.zip'
function isZip(filename) {
// last 4 characters in filename
let ss = filename.slice(filename.length-4, filename.length);
return ss === '.zip';
}
// deletes the zip specified by filename found in the ./zips/ directory
function deleteZip(filename) {
let path = './zips/' + filename;
if (fs.existsSync(path)) {
fs.unlinkSync(path);
}
}
// checks if a file specified by filename is at least two weeks old and deletes if so
// NOTE: checks age by parsing the filename itself, not metadata
function deleteIfOlderThanTwoWeeks(filename, currentDayInt) {
let fileDayInt = getIntegerDayFromDateString(filename.slice(0, filename.length-4));
if (fileDayInt <= currentDayInt) {
if ((currentDayInt - fileDayInt) >= 14) {
deleteZip(filename);
}
}
// edge case: new month
else {
if (((31 - fileDayInt) + currentDayInt) >= 15) {
deleteZip(filename);
}
}
}
// checks all zips in the './zips' folder and deletes those which are at least 2 weeks old
function removeZipFilesOlderThanTwoWeeks() {
let currentDayInt = getIntegerDayFromDateString(getCurrentDateString());
let files = fs.readdirSync('./zips/');
for (let i = 0; i < files.length; i++) {
if (isZip(files[i])) {
deleteIfOlderThanTwoWeeks(files[i], currentDayInt);
}
}
}
// creates a new zip file containing the contents of the ./backups/ directory.
// deletes contents of ./backups/ if it confirms that the zip file was successfully
// created. also clears zip files older than two weeks
//
// NOTE - this is the only function exposed by exports, and is the way which main
// will initiate backup generation
exports.updateBackups = function() {
let nameOfNewZip = getCurrentDateString() + '.zip';
createZipFromBackupDirectories(nameOfNewZip);
if (fs.existsSync('./zips/' + nameOfNewZip)) {
let zipCreated = new AdmZip('./zips/' + nameOfNewZip);
let zipEntries = zipCreated.getEntries();
logger.log('zip ' + nameOfNewZip + ' length ' + zipEntries.length);
let logstring = "";
zipEntries.forEach(function(zipEntry) {
logstring += zipEntry.toString(); // outputs zip entries information
});
logger.log(logstring); // log info about each entry in new zip
if (zipEntries.length >= 6) {
removeUnzippedBackupFiles();
}
else {
logger.errorLog('not enough entries in backup zip; not deleting backup files');
}
}
else {
logger.errorLog('tried creating new zip but no new zip found - not deleting backup files');
}
try {
removeZipFilesOlderThanTwoWeeks();
}
catch (e) {
logger.errorLog(' error removing zip files: ' + e.message + e.stack);
}
}
testDayStringConverter = function() {
console.log(getIntegerDayFromDateString(getCurrentDateString()));
console.log(getIntegerDayFromDateString('2017-7-04-16-48'))
console.log(getIntegerDayFromDateString('2017-7-4-16-48'))
}