selbackup 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +11 -0
  3. data/Gemfile.lock +48 -0
  4. data/LICENSE +14 -0
  5. data/README.fr.md +82 -0
  6. data/README.md +83 -0
  7. data/Rakefile +26 -0
  8. data/doc/apple-touch-icon.png +0 -0
  9. data/doc/classes/Object.html +121 -0
  10. data/doc/classes/SelBackup.html +1387 -0
  11. data/doc/created.rid +6 -0
  12. data/doc/css/github.css +129 -0
  13. data/doc/css/main.css +333 -0
  14. data/doc/css/panel.css +384 -0
  15. data/doc/css/reset.css +48 -0
  16. data/doc/favicon.ico +0 -0
  17. data/doc/files/Gemfile.html +84 -0
  18. data/doc/files/Guardfile.html +147 -0
  19. data/doc/files/LICENSE.html +86 -0
  20. data/doc/files/Rakefile.html +101 -0
  21. data/doc/files/backup-to-s3_rb.html +85 -0
  22. data/doc/files/lib/selbackup_rb.html +89 -0
  23. data/doc/files/lib-backup_rb.html +89 -0
  24. data/doc/files/mv_files_rb.html +89 -0
  25. data/doc/files/spec/selbackup_spec_rb.html +76 -0
  26. data/doc/files/test/lib-backup_test_rb.html +76 -0
  27. data/doc/i/arrows.png +0 -0
  28. data/doc/i/results_bg.png +0 -0
  29. data/doc/i/tree_bg.png +0 -0
  30. data/doc/index.html +13 -0
  31. data/doc/js/highlight.pack.js +1 -0
  32. data/doc/js/jquery-1.3.2.min.js +19 -0
  33. data/doc/js/jquery-effect.js +593 -0
  34. data/doc/js/main.js +24 -0
  35. data/doc/js/navigation.js +142 -0
  36. data/doc/js/search_index.js +1 -0
  37. data/doc/js/searchdoc.js +449 -0
  38. data/doc/js/searcher.js +228 -0
  39. data/doc/panel/index.html +73 -0
  40. data/doc/panel/links.html +16 -0
  41. data/doc/panel/tree.js +1 -0
  42. data/lib/selbackup.rb +376 -0
  43. data/selbackup.gemspec +13 -0
  44. data/spec/selbackup_spec.rb +240 -0
  45. data/upload_test/create_files.sh +13 -0
  46. metadata +88 -0
@@ -0,0 +1,228 @@
1
+ Searcher = function(data) {
2
+ this.data = data;
3
+ this.handlers = [];
4
+ }
5
+
6
+ Searcher.prototype = new function() {
7
+ // search is performed in chunks of 1000 for non-blocking user input
8
+ var CHUNK_SIZE = 1000;
9
+ // do not try to find more than 100 results
10
+ var MAX_RESULTS = 100;
11
+ var huid = 1;
12
+ var suid = 1;
13
+ var runs = 0;
14
+
15
+ this.find = function(query) {
16
+ var queries = splitQuery(query);
17
+ var regexps = buildRegexps(queries);
18
+ var highlighters = buildHilighters(queries);
19
+ var state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++};
20
+ var _this = this;
21
+
22
+ this.currentSuid = state.n;
23
+
24
+ if (!query) return;
25
+
26
+ var run = function() {
27
+ // stop current search thread if new search started
28
+ if (state.n != _this.currentSuid) return;
29
+
30
+ var results =
31
+ performSearch(_this.data, regexps, queries, highlighters, state);
32
+ var hasMore = (state.limit > 0 && state.pass < 4);
33
+
34
+ triggerResults.call(_this, results, !hasMore);
35
+ if (hasMore) {
36
+ setTimeout(run, 2);
37
+ }
38
+ runs++;
39
+ };
40
+ runs = 0;
41
+
42
+ // start search thread
43
+ run();
44
+ }
45
+
46
+ /* ----- Events ------ */
47
+ this.ready = function(fn) {
48
+ fn.huid = huid;
49
+ this.handlers.push(fn);
50
+ }
51
+
52
+ /* ----- Utilities ------ */
53
+ function splitQuery(query) {
54
+ return jQuery.grep(query.split(/(\s+|::?|\(\)?)/), function(string) {
55
+ return string.match(/\S/)
56
+ });
57
+ }
58
+
59
+ function buildRegexps(queries) {
60
+ return jQuery.map(queries, function(query) {
61
+ return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i')
62
+ });
63
+ }
64
+
65
+ function buildHilighters(queries) {
66
+ return jQuery.map(queries, function(query) {
67
+ return jQuery.map(query.split(''), function(l, i) {
68
+ return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2);
69
+ }).join('');
70
+ });
71
+ }
72
+
73
+ // function longMatchRegexp(index, longIndex, regexps) {
74
+ // for (var i = regexps.length - 1; i >= 0; i--){
75
+ // if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
76
+ // };
77
+ // return true;
78
+ // }
79
+
80
+
81
+ /* ----- Mathchers ------ */
82
+
83
+ /*
84
+ * This record matches if the index starts with queries[0] and the record
85
+ * matches all of the regexps
86
+ */
87
+ function matchPassBeginning(index, longIndex, queries, regexps) {
88
+ if (index.indexOf(queries[0]) != 0) return false;
89
+ for (var i=1, l = regexps.length; i < l; i++) {
90
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
91
+ return false;
92
+ };
93
+ return true;
94
+ }
95
+
96
+ /*
97
+ * This record matches if the longIndex starts with queries[0] and the
98
+ * longIndex matches all of the regexps
99
+ */
100
+ function matchPassLongIndex(index, longIndex, queries, regexps) {
101
+ if (longIndex.indexOf(queries[0]) != 0) return false;
102
+ for (var i=1, l = regexps.length; i < l; i++) {
103
+ if (!longIndex.match(regexps[i]))
104
+ return false;
105
+ };
106
+ return true;
107
+ }
108
+
109
+ /*
110
+ * This record matches if the index contains queries[0] and the record
111
+ * matches all of the regexps
112
+ */
113
+ function matchPassContains(index, longIndex, queries, regexps) {
114
+ if (index.indexOf(queries[0]) == -1) return false;
115
+ for (var i=1, l = regexps.length; i < l; i++) {
116
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
117
+ return false;
118
+ };
119
+ return true;
120
+ }
121
+
122
+ /*
123
+ * This record matches if regexps[0] matches the index and the record
124
+ * matches all of the regexps
125
+ */
126
+ function matchPassRegexp(index, longIndex, queries, regexps) {
127
+ if (!index.match(regexps[0])) return false;
128
+ for (var i=1, l = regexps.length; i < l; i++) {
129
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
130
+ return false;
131
+ };
132
+ return true;
133
+ }
134
+
135
+
136
+ /* ----- Highlighters ------ */
137
+ function highlightRegexp(info, queries, regexps, highlighters) {
138
+ var result = createResult(info);
139
+ for (var i=0, l = regexps.length; i < l; i++) {
140
+ result.title = result.title.replace(regexps[i], highlighters[i]);
141
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
142
+ };
143
+ return result;
144
+ }
145
+
146
+ function hltSubstring(string, pos, length) {
147
+ return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length);
148
+ }
149
+
150
+ function highlightQuery(info, queries, regexps, highlighters) {
151
+ var result = createResult(info);
152
+ var pos = 0;
153
+ var lcTitle = result.title.toLowerCase();
154
+
155
+ pos = lcTitle.indexOf(queries[0]);
156
+ if (pos != -1) {
157
+ result.title = hltSubstring(result.title, pos, queries[0].length);
158
+ }
159
+
160
+ result.namespace = result.namespace.replace(regexps[0], highlighters[0]);
161
+ for (var i=1, l = regexps.length; i < l; i++) {
162
+ result.title = result.title.replace(regexps[i], highlighters[i]);
163
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
164
+ };
165
+ return result;
166
+ }
167
+
168
+ function createResult(info) {
169
+ var result = {};
170
+ result.title = info[0];
171
+ result.namespace = info[1];
172
+ result.path = info[2];
173
+ result.params = info[3];
174
+ result.snippet = info[4];
175
+ return result;
176
+ }
177
+
178
+ /* ----- Searching ------ */
179
+ function performSearch(data, regexps, queries, highlighters, state) {
180
+ var searchIndex = data.searchIndex;
181
+ var longSearchIndex = data.longSearchIndex;
182
+ var info = data.info;
183
+ var result = [];
184
+ var i = state.from;
185
+ var l = searchIndex.length;
186
+ var togo = CHUNK_SIZE;
187
+ var matchFunc, hltFunc;
188
+
189
+ while (state.pass < 4 && state.limit > 0 && togo > 0) {
190
+ if (state.pass == 0) {
191
+ matchFunc = matchPassBeginning;
192
+ hltFunc = highlightQuery;
193
+ } else if (state.pass == 1) {
194
+ matchFunc = matchPassLongIndex;
195
+ hltFunc = highlightQuery;
196
+ } else if (state.pass == 2) {
197
+ matchFunc = matchPassContains;
198
+ hltFunc = highlightQuery;
199
+ } else if (state.pass == 3) {
200
+ matchFunc = matchPassRegexp;
201
+ hltFunc = highlightRegexp;
202
+ }
203
+
204
+ for (; togo > 0 && i < l && state.limit > 0; i++, togo--) {
205
+ if (info[i].n == state.n) continue;
206
+ if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) {
207
+ info[i].n = state.n;
208
+ result.push(hltFunc(info[i], queries, regexps, highlighters));
209
+ state.limit--;
210
+ }
211
+ };
212
+ if (searchIndex.length <= i) {
213
+ state.pass++;
214
+ i = state.from = 0;
215
+ } else {
216
+ state.from = i;
217
+ }
218
+ }
219
+ return result;
220
+ }
221
+
222
+ function triggerResults(results, isLast) {
223
+ jQuery.each(this.handlers, function(i, fn) {
224
+ fn.call(this, results, isLast)
225
+ })
226
+ }
227
+ }
228
+
@@ -0,0 +1,73 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
3
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4
+
5
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
6
+ <head>
7
+ <title>search index</title>
8
+ <link rel="stylesheet" href="../css/reset.css" type="text/css" media="screen" charset="utf-8" />
9
+ <link rel="stylesheet" href="../css/panel.css" type="text/css" media="screen" charset="utf-8" />
10
+ <script src="../js/search_index.js" type="text/javascript" charset="utf-8"></script>
11
+ <script src="../js/searcher.js" type="text/javascript" charset="utf-8"></script>
12
+ <script src="tree.js" type="text/javascript" charset="utf-8"></script>
13
+ <script src="../js/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
14
+ <script src="../js/searchdoc.js" type="text/javascript" charset="utf-8"></script>
15
+ <script type="text/javascript" charset="utf-8">
16
+ function placeholder() {
17
+ if ($('<input type="text">')[0].placeholder !== undefined) return;
18
+
19
+ $('#search-label').click(function() {
20
+ $('#search').focus();
21
+ $('#search-label').hide();
22
+ });
23
+
24
+ $('#search').focus(function() {
25
+ $('#search-label').hide();
26
+ });
27
+ $('#search').blur(function() {
28
+ this.value == '' && $('#search-label').show()
29
+ });
30
+
31
+ $('#search')[0].value == '' && $('#search-label').show();
32
+ }
33
+ $(function() {
34
+ placeholder();
35
+ $('#links').hide();
36
+ var panel = new Searchdoc.Panel($('#panel'), search_data, tree, window.parent.frames[1]);
37
+ $('#search').focus();
38
+
39
+ var s = window.parent.location.search.match(/\?q=([^&]+)/);
40
+ if (s) {
41
+ s = decodeURIComponent(s[1]).replace(/\+/g, ' ');
42
+ if (s.length > 0)
43
+ {
44
+ $('#search').val(s);
45
+ panel.search(s, true);
46
+ }
47
+ }
48
+ })
49
+ </script>
50
+ </head>
51
+ <body>
52
+ <div class="panel panel_tree" id="panel">
53
+ <div class="header">
54
+ <div>
55
+ <label for="search" id="search-label" style="display: none">Search</label>
56
+ <table>
57
+ <tr><td>
58
+ <input type="Search" placeholder="Search" autosave="searchdoc" results="10" id="search" autocomplete="off"/>
59
+ </td></tr>
60
+ </table></div>
61
+ </div>
62
+ <div class="tree">
63
+ <ul>
64
+ </ul>
65
+ </div>
66
+ <div class="result">
67
+ <ul>
68
+ </ul>
69
+ </div>
70
+ </div>
71
+ <a href="links.html" id="links">index</a>
72
+ </body>
73
+ </html>
@@ -0,0 +1,16 @@
1
+ <html>
2
+ <head>File index</head>
3
+ <body>
4
+
5
+ <a href="../files/Gemfile.html">Gemfile</a>
6
+
7
+ <a href="../files/LICENSE.html">LICENSE</a>
8
+
9
+ <a href="../files/Rakefile.html">Rakefile</a>
10
+
11
+ <a href="../files/lib/selbackup_rb.html">lib/selbackup.rb</a>
12
+
13
+ <a href="../files/spec/selbackup_spec_rb.html">spec/selbackup_spec.rb</a>
14
+
15
+ </body>
16
+ </html>
data/doc/panel/tree.js ADDED
@@ -0,0 +1 @@
1
+ var tree = [["","","files",[["Gemfile","files/Gemfile.html","",[]],["LICENSE","files/LICENSE.html","",[]],["Rakefile","files/Rakefile.html","",[]],["","","lib",[["selbackup.rb","files/lib/selbackup_rb.html","",[]]]],["","","spec",[["selbackup_spec.rb","files/spec/selbackup_spec_rb.html","",[]]]]]],["SelBackup","classes/SelBackup.html"," < Object",[]]]
data/lib/selbackup.rb ADDED
@@ -0,0 +1,376 @@
1
+ require 'active_support/core_ext'
2
+ require 'fog'
3
+
4
+ # SelBackup Class
5
+ #
6
+ # Enables connection to s3 server and uploads files
7
+ class SelBackup
8
+ # Attributes: informations required for connection to s3 server
9
+ attr_accessor :access_key, :access_secret, :bucket_name, :region
10
+
11
+
12
+ # Public: Initialize a new SelBackup instance.
13
+ #
14
+ # key:: A String representing the AWS ACCESS KEY ID.
15
+ #
16
+ # secret:: A String representing the AWS ACCESS KEY SECRET.
17
+ #
18
+ # bucket:: A String representing the name of the bucket ot use.
19
+ #
20
+ # :region (optional):: A String representing the region to conect to
21
+ # (default: 'eu-west-1').
22
+ #
23
+ # Examples
24
+ #
25
+ # SelectraBackup.new('key', 'secret', 'bucket', region: 'us-east-1')
26
+ #
27
+ # Returns the newly instanciated object.
28
+ def initialize(key, secret, bucket, region = 'eu-west-1')
29
+ @access_key = key
30
+ @access_secret = secret
31
+ @bucket_name = bucket
32
+ @region = region
33
+ end
34
+
35
+
36
+ # Public: Returns the S3 bucket.
37
+ #
38
+ # Returns a Fog::Storage::AWS::Directory instance.
39
+ def bucket
40
+ @bucket ||= connection.directories.get(bucket_name)
41
+ end
42
+
43
+
44
+ # Public: daily check algorythm
45
+ #
46
+ # filename:: String which contains a filename. If you upload '2013-01-01-file.tgz', filename will be 'file.tgz'
47
+ #
48
+ # * If 7 daily files or less: does nothing
49
+ #
50
+ # * If more than 7 daily files but less than one week datediff between the latest daily file and the most recent weekly file: deletes the latest daily file
51
+ #
52
+ # * If more than 7 daily files but less than one week datediff between the latest daily file and the most recent weekly file: pushes the latest daily file to weekly file
53
+ # 2013-01-01-daily-file.tgz -> 2013-01-01-weekly-file.tgz
54
+ #
55
+ # Returns true if a file as been push. False in other cases
56
+ def check_daily(filename, nb_day)
57
+ return_value = false
58
+ daily_directory = give_me_files(filename, "daily")
59
+ if ! daily_good?(daily_directory, nb_day)
60
+ weekly_directory = give_me_files(filename, "weekly")
61
+ latest_daily_file = give_me_latest_file(daily_directory)
62
+ recent_weekly_file = give_me_recent_file(weekly_directory)
63
+ if weekly_directory == [] || should_weekly?(latest_daily_file.key, recent_weekly_file.key)
64
+ weekly_file = gen_weekly_file({ key: latest_daily_file.key, body: latest_daily_file.body})
65
+ push_file(weekly_file)
66
+ return_value = true
67
+ end
68
+ delete_file(latest_daily_file)
69
+ end
70
+ return return_value
71
+ end
72
+
73
+
74
+ # Public: montlhy check algorythm
75
+ #
76
+ # filename:: String which contains a filename. If you upload '2013-01-01-file.tgz', filename will be 'file.tgz'
77
+ #
78
+ # * If 3 monthly files or less: does nothing
79
+ #
80
+ # * if more than 3 monthly files: deletes the latest monthly file
81
+ #
82
+ # Returns true if a file as been delete. False in other cases
83
+ def check_monthly(filename, nb_month)
84
+ return_value = false
85
+ monthly_directory = give_me_files(filename, "monthly")
86
+ if ! monthly_good?(monthly_directory, nb_month)
87
+ latest_monthly_file = give_me_latest_file(monthly_directory)
88
+ delete_file(latest_monthly_file)
89
+ return_value = true
90
+ end
91
+ return return_value
92
+ end
93
+
94
+
95
+ # Public: weekly check algorythm
96
+ #
97
+ # filename:: String which contains a filename. If you upload '2013-01-01-file.tgz', filename will be 'file.tgz'
98
+ #
99
+ # * If 4 weekly files or less: does nothing
100
+ #
101
+ # * If more than 4 weekly files but less than one month datediff between the latest weekly file and the most recent monthly file: deletes the latest weekly file
102
+ #
103
+ # * If more than 4 weekly files but less than one week datediff between the latest weekly file and the most recent monthly file: pushes the latest weekly file to monthly file
104
+ # 2013-01-01-weekly-file.tgz -> 2013-01-01-monthly-file.tgz
105
+ #
106
+ # Returns true if a file as been push. False in other cases
107
+ def check_weekly(filename, nb_week)
108
+ return_value = false
109
+ weekly_directory = give_me_files(filename, "weekly")
110
+ if ! weekly_good?(weekly_directory, nb_week)
111
+ monthly_directory = give_me_files(filename, "monthly")
112
+ latest_weekly_file = give_me_latest_file(weekly_directory)
113
+ recent_monthly_file = give_me_recent_file(monthly_directory)
114
+ if monthly_directory == [] || should_monthly?(latest_weekly_file.key, recent_monthly_file.key)
115
+ monthly_file = gen_monthly_file({ key: latest_weekly_file.key, body: latest_weekly_file.body})
116
+ push_file(monthly_file)
117
+ return_value = true
118
+ end
119
+ delete_file(latest_weekly_file)
120
+ end
121
+ return return_value
122
+ end
123
+
124
+
125
+ # Public: Returns the S3 connection.
126
+ #
127
+ # Returns a Fog::Storage::AWS::Real instance.
128
+ def connection
129
+ @connection ||= Fog::Storage.new(provider: 'AWS', aws_access_key_id: access_key, aws_secret_access_key: access_secret, region: region)
130
+ end
131
+
132
+
133
+ # Public: Check daily files number
134
+ #
135
+ # directoryFiles:: Array of daily files
136
+ # ['file/2013-01-01-daily-file.tgz', 'file/2013-01-02-daily-file.tgz', ...]
137
+ #
138
+ # Returns false if there is more than 7 daily files. False in other cases
139
+ def daily_good?(directoryFiles, nb_day)
140
+ return directoryFiles.length > nb_day ? false : true;
141
+ end
142
+
143
+
144
+ # Public: deletes a file
145
+ #
146
+ # file:: Fog::Storage::AWS::Files file
147
+ #
148
+ # returns nothing
149
+ def delete_file(file)
150
+ file.destroy
151
+ end
152
+
153
+
154
+ # Public: Returns a virtual S3 directory.
155
+ #
156
+ # S3 doesn't know such a thing as a directory but it is possible to use a prefix to select only the files having a key starting with this prefix.
157
+ #
158
+ # path:: A String representing the prefix to use.
159
+ #
160
+ # Examples
161
+ #
162
+ # sb = SelectraBackup.new('key', 'secret', 'bucket')
163
+ # backup = sb.directory('backup/')
164
+ # backup.files
165
+ # # => <Fog::Storage::AWS::Files ...>
166
+ #
167
+ # Returns a Fog::Storage::AWS::Directory instance.
168
+ def directory(path)
169
+ connection.directories.get(bucket_name, prefix: path)
170
+ end
171
+
172
+
173
+ # Public: Returns the list of files.
174
+ #
175
+ # Returns a Fog::Storage::AWS::Files instances.
176
+ def files
177
+ bucket.files
178
+ end
179
+
180
+
181
+ # Public: returns lists of file
182
+ #
183
+ # filename: "file.tgz" for example
184
+ #
185
+ # type: specify if you want daily, weekly or monthly files
186
+ #
187
+ # Returns a sorted array
188
+ def give_me_files(filename, type)
189
+ full_directory = directory("#{filename}/")
190
+ files = []
191
+ full_directory.files.each do | file |
192
+ if file.key =~ /#{filename}\/\d{4}-\d{2}-\d{2}-#{type}-[\w+.]+/ ||
193
+ file.key =~ /#{filename}\/#{type}-\d{4}-\d{2}-\d{2}-[\w+.]+/
194
+ files.push(file)
195
+ end
196
+ end
197
+ return files
198
+ end
199
+
200
+
201
+ # Public: returns latest file
202
+ #
203
+ # files: array of AWS object file
204
+ #
205
+ # Returns the latest file, based on the date
206
+ def give_me_latest_file(files)
207
+ latest_file = files.first
208
+ files.each do | file |
209
+ if Date.parse(file.key.gsub('-', '')) < Date.parse(latest_file.key.gsub('-', ''))
210
+ latest_file = file
211
+ end
212
+ end
213
+ return latest_file
214
+ end
215
+
216
+
217
+ # Public: returns most recent file
218
+ #
219
+ # files: array of AWS object file
220
+ #
221
+ # Returns the most recent file, based on the date
222
+ def give_me_recent_file(files)
223
+ recent_file = files.first
224
+ files.each do | file |
225
+ if Date.parse(file.key.gsub('-', '')) > Date.parse(recent_file.key.gsub('-', ''))
226
+ recent_file = file
227
+ end
228
+ end
229
+ return recent_file
230
+ end
231
+
232
+
233
+ # Public: Check monthly files number
234
+ #
235
+ # files:: Array of monthly files
236
+ # ['file/2013-01-01-monthly-file.tgz', 'file/2013-01-02-monthly-file.tgz', ...]
237
+ #
238
+ # Returns false if there is more than 3 monthly files. False in other cases
239
+ def monthly_good?(files, nb_month)
240
+ return files.length > nb_month ? false : true
241
+ end
242
+
243
+
244
+ # Public: gen a daily file
245
+ #
246
+ # file:: file you want to upload
247
+ #
248
+ # Returns an hash containing the filename, the key and the body of the daily file
249
+ def gen_daily_file(file)
250
+ name = File.basename(file)
251
+ if name =~ /[0-9]{4}-[0-9]{2}-[0-9]{2}(\.\w*)?$/
252
+ return false
253
+ elsif !(name =~ /[0-9]{4}-[0-9]{2}-[0-9]{2}-/)
254
+ name = "#{Date.today.to_s}-#{name}"
255
+ end
256
+ myname = name.split(/[0-9]{4}-[0-9]{2}-[0-9]{2}-/).last
257
+ mydate = name.split("-#{myname}").first
258
+ key = "#{myname}/#{mydate}-daily-#{myname}"
259
+ return { myname: myname, key: key, body: File.open(file) }
260
+ end
261
+
262
+
263
+ # Public: gen a monthly file
264
+ #
265
+ # file:: hash containing the key and the body of the weekly file you want to push to monthly file
266
+ #
267
+ # Returns an hash containing the key and the body of the monthly file
268
+ def gen_monthly_file(file)
269
+ if file[:key] =~ /[\w+.-]+\/[\w+.-]+-\d{4}-\d{2}-\d{2}-[\w+.-]+/
270
+ monthly_name = file[:key].sub("/weekly-", "/monthy-")
271
+ else
272
+ monthly_name = file[:key].sub("-weekly-", "-monthly-")
273
+ end
274
+ return { key: monthly_name, body: file[:body] }
275
+ end
276
+
277
+
278
+ # Public: gen a weekly file
279
+ #
280
+ # file:: hash containing the key and the body of the daily file you want to push to weekly file
281
+ #
282
+ # Returns an hash containing the key and the body of the weekly file
283
+ def gen_weekly_file(file)
284
+ if file[:key] =~ /[\w+.-]+\/[\w+.-]+-\d{4}-\d{2}-\d{2}-[\w+.-]+/
285
+ weekly_name = file[:key].sub("/daily-", "/weekly-")
286
+ else
287
+ weekly_name = file[:key].sub("-daily-", "-weekly-")
288
+ end
289
+ return { key: weekly_name, body: file[:body] }
290
+ end
291
+
292
+
293
+ # Public: pushes a file to s3 server
294
+ #
295
+ # file:: hash containing the key and the body of the file you want to upload
296
+ #
297
+ # Returns nothing
298
+ def push_file(file)
299
+ if file[:key] =~ /[\w+.-]+\/[\w+.-]+-\d{4}-\d{2}-\d{2}-[\w+.-]+/
300
+ filename = file[:key].split('/').first
301
+ name_parts = file[:key].split('/').last.split('-')
302
+ file[:key] = "#{filename}/#{name_parts[1]}-#{name_parts[2]}-#{name_parts[3]}-#{name_parts[0]}-#{filename}"
303
+ end
304
+ bucket.files.create(key: file[:key], body: file[:body])
305
+ end
306
+
307
+
308
+ # Public: date diff
309
+ #
310
+ # file1:: latest daily file
311
+ #
312
+ # file2:: most recent weekly file
313
+ #
314
+ # Returns true if datediff between the two files is upper than 7 days. False in other cases
315
+ def should_weekly?(file1, file2)
316
+ begin
317
+ date1 = Date.parse(file1.gsub('-', ''))
318
+ date2 = Date.parse(file2.gsub('-', ''))
319
+ rescue
320
+ print "Wrong date (Date.parse in should_monthly)."
321
+ return false
322
+ end
323
+ date_diff = date1 - date2
324
+ return date_diff.abs >= 7 ? true : false
325
+ end
326
+
327
+
328
+ # Public: date diff
329
+ #
330
+ # file1:: latest weekly file
331
+ #
332
+ # file2:: most recent monthly file
333
+ #
334
+ # Returns true if datediff between the two files is upper than 1 month. False in other cases
335
+ def should_monthly?(file1, file2)
336
+ begin
337
+ date1 = Date.parse(file1.gsub('-', '')).prev_month
338
+ date2 = Date.parse(file2.gsub('-', ''))
339
+ rescue
340
+ print "Wrong date (Date.parse in should_monthly)."
341
+ return false
342
+ end
343
+ return date1 >= date2 ? true : false
344
+ end
345
+
346
+ # Public: upload file algorythm
347
+ #
348
+ # file:: file you want to upload
349
+ #
350
+ # Uploads file as daily file and check daily, weekly and monthly full.
351
+ #
352
+ # Returns nothing
353
+ def upload_file(file, nb_day = 7, nb_week = 4, nb_month = 3)
354
+ daily_file = gen_daily_file(file)
355
+ if daily_file == false
356
+ return false
357
+ end
358
+ push_file(daily_file)
359
+ if check_daily(daily_file[:myname], nb_day)
360
+ if check_weekly(daily_file[:myname], nb_week)
361
+ check_monthly(daily_file[:myname], nb_month)
362
+ end
363
+ end
364
+ end
365
+
366
+
367
+ # Public: Check weekly files number
368
+ #
369
+ # files:: Array of daily files
370
+ # ['file/2013-01-01-weekly-file.tgz', 'file/013-01-02-weekly-2file.tgz', ...]
371
+ #
372
+ # Returns false if there is more than 4 weekly files. False in other cases
373
+ def weekly_good?(directoryFiles, nb_week)
374
+ return directoryFiles.length > nb_week ? false : true
375
+ end
376
+ end