qdumpfs 0.7.0 → 0.8.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +22 -16
- data/lib/qdumpfs.rb +36 -111
- data/lib/qdumpfs/option.rb +2 -1
- data/lib/qdumpfs/version.rb +4 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc8d8dec60fe04598e9dd5bea8528f5299a7cbb7ee0f0432c3b6d46488917edf
|
4
|
+
data.tar.gz: '029dffccca2865524f208d28f2ebe2f63b2de465e0a5f08de93c597156fd48a9'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9c393b76dddd9978adf5dfc77cfb25f3c14bfb9b1aca0767228b8b4c70fdf11206f4a35c9e0f5098b1c7ba1e3b113dc8f51de3ad14b48d39fe1dff8dd21309f1
|
7
|
+
data.tar.gz: 054605d2b4f91e2c0fdbd0518614b81a9f04f0ba378f0d92c5aba28c59456ae88c40dfb156579295c10130c248fc314197bd03398f18435cd1e0596696f444f2
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
# Qdumpfs
|
2
2
|
|
3
|
-
|
3
|
+
pdumpfsの個人的改良版です。
|
4
4
|
|
5
|
-
|
5
|
+
Gem化して最近のバージョンのバージョンのRubyに対応。コマンドの拡張などを行っています。
|
6
6
|
|
7
|
-
|
7
|
+
## インストール
|
8
8
|
|
9
|
-
|
9
|
+
gem install qdumpfs
|
10
10
|
|
11
|
+
## 使用方法
|
11
12
|
|
12
13
|
```
|
13
14
|
Usage: qdumpfs [options] <source> <dest>
|
@@ -19,48 +20,53 @@ Options
|
|
19
20
|
-e, --exclude=PATTERN exclude files/directories matching PATTERN
|
20
21
|
-s, --exclude-by-size=SIZE exclude files larger than SIZE
|
21
22
|
-w, --exclude-by-glob=GLOB exclude files matching GLOB
|
22
|
-
-c, --command=COMMAND backup|sync|list|expire|verify|
|
23
|
+
-c, --command=COMMAND backup|sync|list|expire|verify|delete
|
23
24
|
-l, --limit=HOURS limit hours
|
24
25
|
-k, --keep=KEEPARG ex: --keep 100Y12M12W30D (100years, 12months, 12weeks, 30days, default)
|
25
26
|
```
|
26
27
|
|
27
|
-
##
|
28
|
+
## 実行例
|
29
|
+
|
30
|
+
|
31
|
+
バックアップを実行する場合。
|
28
32
|
|
29
|
-
Backup your home directory, run the following command.
|
30
33
|
```
|
31
34
|
qdumpfs /home/foo /backup
|
32
35
|
```
|
33
36
|
|
34
|
-
|
37
|
+
"--command backup"オプションを明示することもできます。
|
38
|
+
|
35
39
|
```
|
36
40
|
qdumpfs --command=backup /home/foo /backup
|
37
41
|
```
|
38
42
|
|
39
|
-
|
43
|
+
"--command sync"でバックアップフォルダを同期できます。
|
40
44
|
```
|
41
45
|
qdumpfs --command=sync /backup1 /backup2
|
42
46
|
```
|
43
47
|
|
44
|
-
|
48
|
+
バックアップフォルダの同期には膨大な時間が必要な場合があるため、実行時間を制限できます。以下は例えば1時間に制限する場合です。
|
45
49
|
```
|
46
50
|
qdumpfs --command=sync --limit=1 /backup1 /backup2
|
47
51
|
```
|
48
52
|
|
49
|
-
|
53
|
+
バックアップフォルダの同期で、1時間でかつ"100Y12M12W30D"を保存する場合のオプションです。
|
50
54
|
```
|
51
|
-
qdumpfs --command=sync --limit=1 --keep=5Y6M7W10D
|
55
|
+
qdumpfs --command=sync --limit=1 --keep=5Y6M7W10D backup1 /backup2
|
52
56
|
```
|
53
57
|
|
54
|
-
|
58
|
+
"--command expire"で、"--keep="パターンに該当しないバックアップを削除できます。
|
55
59
|
```
|
56
|
-
qdumpfs --command=expire --limit=1 --keep=5Y6M7W10D
|
60
|
+
qdumpfs --command=expire --limit=1 --keep=5Y6M7W10D backup1 /backup2
|
57
61
|
```
|
58
62
|
|
63
|
+
"--command delete"で、バックアップに存在する指定したパスを削除できます(間違えてバックアップした内容を削除したい場合などに使用)。
|
64
|
+
```
|
65
|
+
qdumpfs --command=delete --delete-dir=backup1 --limit=1 r:/backup2
|
66
|
+
```
|
59
67
|
|
60
68
|
## License
|
61
69
|
|
62
70
|
qdumpfs is a free software with ABSOLUTELY NO WARRANTY under the terms of the GNU General Public License version 2.
|
63
71
|
|
64
72
|
|
65
|
-
|
66
|
-
|
data/lib/qdumpfs.rb
CHANGED
@@ -45,6 +45,9 @@ module Qdumpfs
|
|
45
45
|
opt.on('--delete-to=YYYYMMDD', 'delete backup to YYYY/MM/DD') {|v|
|
46
46
|
opts[:delete_to] = Date.parse(v)
|
47
47
|
}
|
48
|
+
opt.on('--delete-dir=DIRS', 'relative path from the snapshot root of the backup. ex: --delete-dir=foo,home/bar') {|v|
|
49
|
+
opts[:delete_dirs] = v.split(/,/)
|
50
|
+
}
|
48
51
|
opt.on('--backup-at=YYYYMMDD', 'backup at YYYY/MM/DD') {|v|
|
49
52
|
opts[:backup_at] = Date.parse(v)
|
50
53
|
}
|
@@ -85,8 +88,6 @@ module Qdumpfs
|
|
85
88
|
verify
|
86
89
|
elsif @opt.cmd == 'delete'
|
87
90
|
delete('delete')
|
88
|
-
# elsif @opt.cmd == 'test'
|
89
|
-
# test
|
90
91
|
else
|
91
92
|
raise RuntimeError, "unknown command: #{@opt.cmd}"
|
92
93
|
end
|
@@ -149,29 +150,6 @@ module Qdumpfs
|
|
149
150
|
return src_count, dst_count
|
150
151
|
end
|
151
152
|
|
152
|
-
# def get_snapshots(target_dir)
|
153
|
-
# # 指定したディレクトリに含まれるバックアップフォルダ(日付つき)を全て取得
|
154
|
-
# dd = "[0-9][0-9]"
|
155
|
-
# dddd = dd + dd
|
156
|
-
# # FIXME: Y10K problem.
|
157
|
-
# dirs = []
|
158
|
-
# glob_path = File.join(target_dir, dddd, dd, dd)
|
159
|
-
# Dir.glob(glob_path).sort.find {|dir|
|
160
|
-
# day, month, year = File.split_all(dir).reverse.map {|x| x.to_i }
|
161
|
-
# path = diro
|
162
|
-
# if File.directory?(path) and Date.valid_date?(year, month, day) and
|
163
|
-
# dirs << path
|
164
|
-
# end
|
165
|
-
# }
|
166
|
-
# dirs
|
167
|
-
# end
|
168
|
-
|
169
|
-
# def get_snapshot_date(snapshot)
|
170
|
-
# # バックアップディレクトリのパス(日付つき)から日付を取得して返す
|
171
|
-
# day, month, year = File.split_all(snapshot).reverse.map {|x| x.to_i }
|
172
|
-
# Time.new(year, month, day)
|
173
|
-
# end
|
174
|
-
|
175
153
|
def update_snapshot(src, latest, today)
|
176
154
|
# バックアップの差分コピーを実行
|
177
155
|
# src: コピー元ディレクトリ ex) i:/from/home
|
@@ -457,9 +435,7 @@ module Qdumpfs
|
|
457
435
|
|
458
436
|
def delete(cmd)
|
459
437
|
@opt.validate_directories(1)
|
460
|
-
|
461
438
|
start_time = Time.now
|
462
|
-
p @opt.limit_sec
|
463
439
|
limit_time = start_time + (@opt.limit_sec)
|
464
440
|
log("##### #{cmd} delete-from=#{@opt.delete_from} delete-to=#{@opt.delete_to} start #{fmt(start_time)} => limit_time=#{fmt(limit_time)} #####")
|
465
441
|
@opt.dirs.each do |target_dir|
|
@@ -482,6 +458,29 @@ p @opt.limit_sec
|
|
482
458
|
log("##### #{cmd} end #####")
|
483
459
|
end
|
484
460
|
|
461
|
+
def rm_dir(path)
|
462
|
+
can_delete = true
|
463
|
+
if @opt.dry_run
|
464
|
+
can_delete = false
|
465
|
+
elsif !FileTest.directory?(path)
|
466
|
+
can_delete = false
|
467
|
+
end
|
468
|
+
msg = can_delete ? "...ok..." : "...ng..."
|
469
|
+
print "Deleting #{path} #{msg}"
|
470
|
+
|
471
|
+
return unless can_delete
|
472
|
+
|
473
|
+
#それ以外は日付バックアップディレクトリ全体を削除
|
474
|
+
if windows?
|
475
|
+
# Windowsの場合
|
476
|
+
win_backup_path = to_win_path(path)
|
477
|
+
system("rmdir /S /Q #{win_backup_path}")
|
478
|
+
else
|
479
|
+
# Linux/macOSの場合
|
480
|
+
system("rm -rf #{path}")
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
485
484
|
def delete_target_dir(cmd, target_dir)
|
486
485
|
target_dir = to_unix_path(target_dir)
|
487
486
|
puts "<<<<< Target dir: #{target_dir} >>>>>"
|
@@ -494,40 +493,20 @@ p @opt.limit_sec
|
|
494
493
|
else
|
495
494
|
raise RuntimeError, "unknown command: #{cmd}"
|
496
495
|
end
|
497
|
-
|
498
|
-
# p @opt.keep_year
|
499
|
-
# p @opt.keep_month
|
500
|
-
# p @opt.keep_day
|
501
|
-
|
496
|
+
|
502
497
|
snapshots.each do |snapshot|
|
503
498
|
next if snapshot.keep
|
504
499
|
t_start = Time.now
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
if windows?
|
513
|
-
# Windowsの場合
|
514
|
-
win_backup_path = to_win_path(snapshot.path)
|
515
|
-
|
516
|
-
# byenow = "byenow"
|
517
|
-
# if which(byenow)
|
518
|
-
# print " bynow"
|
519
|
-
# system("byenow -y --delete-ntapi --one-liner #{snapshot.path}")
|
520
|
-
# else
|
521
|
-
# print " pass1"
|
522
|
-
# system("del /F /S /Q #{win_backup_path} > nul")
|
523
|
-
# print " pass2"
|
524
|
-
# system("rmdir /S /Q #{win_backup_path}")
|
525
|
-
# end
|
526
|
-
system("rmdir /S /Q #{win_backup_path}")
|
527
|
-
else
|
528
|
-
# Linux/macOSの場合
|
529
|
-
system("rm -rf #{snapshot.path}")
|
500
|
+
|
501
|
+
if @opt.delete_dirs.size > 0
|
502
|
+
#削除するディレクトリが指定されている場合日付バックアップディレクトリの下そのディレクトリを削除
|
503
|
+
@opt.delete_dirs.each do |delete_dir|
|
504
|
+
delete_path = File.join(snapshot.path, delete_dir)
|
505
|
+
rm_dir(delete_path)
|
530
506
|
end
|
507
|
+
else
|
508
|
+
#それ以外はバックアップディレクトリ全体が対象
|
509
|
+
rm_dir(snapshot.path)
|
531
510
|
end
|
532
511
|
|
533
512
|
t_end = Time.now
|
@@ -551,60 +530,6 @@ p @opt.limit_sec
|
|
551
530
|
end
|
552
531
|
end
|
553
532
|
|
554
|
-
# def delete
|
555
|
-
# @opt.validate_directories(1)
|
556
|
-
|
557
|
-
# start_time = Time.now
|
558
|
-
# limit_time = start_time + (@opt.limit_sec)
|
559
|
-
# log("##### delete start #{fmt(start_time)} => limit_time=#{fmt(limit_time)} #####")
|
560
|
-
# @opt.dirs.each do |target_dir|
|
561
|
-
# target_start = Time.now
|
562
|
-
# delete_target_dir(target_dir)
|
563
|
-
# target_end = Time.now
|
564
|
-
|
565
|
-
# # 次回expireにかかる時間を最終expire時間の半分と予想
|
566
|
-
# next_expire = (target_end - target_start) / 2
|
567
|
-
|
568
|
-
# cur_time = Time.now
|
569
|
-
# in_imit = (cur_time + next_expire) < limit_time
|
570
|
-
|
571
|
-
# log("## cur_time=#{fmt(cur_time)} + next_expire=#{next_expire} < limit_time=#{fmt(limit_time)} in_limit=#{in_limit} ## ")
|
572
|
-
# unless in_limit
|
573
|
-
# break
|
574
|
-
# end
|
575
|
-
# end
|
576
|
-
# log("##### delete end #####")
|
577
|
-
# end
|
578
|
-
|
579
|
-
# def delete_target_dir(target_dir)
|
580
|
-
# target_dir = to_unix_path(target_dir)
|
581
|
-
# puts "<<<<< Target dir: #{target_dir} >>>>>"
|
582
|
-
|
583
|
-
# snapshots = BackupDir.scan_backup_dirs(target_dir)
|
584
|
-
# @opt.detect_delete_dirs(snapshots)
|
585
|
-
|
586
|
-
# snapshots.each do |snapshot|
|
587
|
-
# next if snapshot.keep
|
588
|
-
# t_start = Time.now
|
589
|
-
# print "Deleting #{snapshot.path} ..."
|
590
|
-
|
591
|
-
# unless @opt.dry_run
|
592
|
-
# if windows?
|
593
|
-
# # Windowsの場合
|
594
|
-
# win_backup_path = to_win_path(snapshot.path)
|
595
|
-
# system("rmdir /S /Q #{win_backup_path}")
|
596
|
-
# else
|
597
|
-
# # Linux/macOSの場合
|
598
|
-
# system("rm -rf #{snapshot.path}")
|
599
|
-
# end
|
600
|
-
# end
|
601
|
-
# end
|
602
|
-
|
603
|
-
# t_end = Time.now
|
604
|
-
# diff = (t_end - t_start).to_i
|
605
|
-
# diff_hours = diff / 3600
|
606
|
-
# puts " done[#{diff} seconds = #{diff_hours} hours]."
|
607
|
-
# end
|
608
533
|
|
609
534
|
end
|
610
535
|
|
data/lib/qdumpfs/option.rb
CHANGED
@@ -141,6 +141,7 @@ module Qdumpfs
|
|
141
141
|
@keep_day = $1.to_i if keep =~ /(\d+)D/
|
142
142
|
@delete_from = @opts[:delete_from]
|
143
143
|
@delete_to = @opts[:delete_to]
|
144
|
+
@delete_dirs = @opts[:delete_dirs]
|
144
145
|
@backup_at = @opts[:backup_at]
|
145
146
|
@today = Date.today
|
146
147
|
end
|
@@ -148,7 +149,7 @@ module Qdumpfs
|
|
148
149
|
attr_reader :keep_year, :keep_month, :keep_week, :keep_day
|
149
150
|
attr_reader :logdir, :logpath, :verifypath
|
150
151
|
attr_reader :logger, :matcher, :reporter, :interval_proc
|
151
|
-
attr_reader :delete_from, :delete_to, :backup_at
|
152
|
+
attr_reader :delete_from, :delete_to, :delete_dirs, :backup_at
|
152
153
|
|
153
154
|
def report(type, filename)
|
154
155
|
if @opts[:v]
|
data/lib/qdumpfs/version.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
-
module Qdumpfs
|
2
|
-
VERSION = "0.
|
3
|
-
end
|
1
|
+
module Qdumpfs
|
2
|
+
VERSION = "0.8.0"
|
3
|
+
end
|
4
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qdumpfs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- src
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|