bakker 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING.txt +676 -0
- data/History.txt +6 -0
- data/Manifest.txt +8 -0
- data/README.txt +136 -0
- data/Rakefile +15 -0
- data/bin/bakker +139 -0
- data/lib/bakker.rb +69 -0
- data/spec/bakker_spec.rb +466 -0
- data.tar.gz.sig +3 -0
- metadata +114 -0
- metadata.gz.sig +2 -0
data/Manifest.txt
ADDED
data/README.txt
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
= Bakker
|
2
|
+
|
3
|
+
* Project: https://rubyforge.org/projects/aef/
|
4
|
+
* RDoc: http://aef.rubyforge.org/bakker/
|
5
|
+
|
6
|
+
== DESCRIPTION:
|
7
|
+
|
8
|
+
Bakker was created to help with simple task of renaming or copying files for
|
9
|
+
quick backup purposes. For instance by creating a copy of a list of files
|
10
|
+
while adding .bak to the copies filenames. Bakker gives you control over the
|
11
|
+
extension to be added to or removed from the file and whether it should be
|
12
|
+
moved or copied.
|
13
|
+
|
14
|
+
== FEATURES/PROBLEMS:
|
15
|
+
|
16
|
+
* Usable as library and commandline tool
|
17
|
+
* Tested and fully working on:
|
18
|
+
* Ubuntu Linux 8.10 i386_64 (Ruby 1.8.7 and 1.9.1p0)
|
19
|
+
* On Windows XP i386 (Ruby 1.8.6)
|
20
|
+
* On Windows XP i386 (Ruby 1.8.6) there were some problems testing the
|
21
|
+
environment variable choices. Two tests are failing but the programs seems
|
22
|
+
to work correctly. If anyone finds the problem, please contact me.
|
23
|
+
* The commandline tool doesn't work with Ruby 1.9.x because the user-choices gem
|
24
|
+
is not yet updated. A patch is available here:
|
25
|
+
https://rubyforge.org/tracker/index.php?func=detail&aid=24307&group_id=4192&atid=16176
|
26
|
+
|
27
|
+
== SYNOPSIS:
|
28
|
+
|
29
|
+
=== Commandline
|
30
|
+
|
31
|
+
The following command renames config.ini to config.ini.bak. You can type the
|
32
|
+
same command a second time to revert the action:
|
33
|
+
|
34
|
+
bakker config.ini
|
35
|
+
|
36
|
+
Instead of renaming you can create a copy of config.xml by using the following
|
37
|
+
command:
|
38
|
+
|
39
|
+
bakker -a copy config.ini
|
40
|
+
|
41
|
+
To change the extension which will be appended or removed from the filename use
|
42
|
+
the following command:
|
43
|
+
|
44
|
+
bakker -e .backup
|
45
|
+
|
46
|
+
In a directory with the follwing contents:
|
47
|
+
|
48
|
+
demo1
|
49
|
+
demo2.bak
|
50
|
+
demo3.bak
|
51
|
+
|
52
|
+
if you use the command:
|
53
|
+
|
54
|
+
bakker *
|
55
|
+
|
56
|
+
you get the following list of files (because by default Bakker toggles the
|
57
|
+
extension):
|
58
|
+
|
59
|
+
demo1.bak
|
60
|
+
demo2
|
61
|
+
demo3
|
62
|
+
|
63
|
+
if you now want every file in the folder to have a .bak extension use the
|
64
|
+
following command:
|
65
|
+
|
66
|
+
bakker -m add *
|
67
|
+
|
68
|
+
the result will look like this:
|
69
|
+
|
70
|
+
demo1.bak
|
71
|
+
demo2.bak
|
72
|
+
demo3.bak
|
73
|
+
|
74
|
+
Instead of using the add-mode you could have used the remove-mode like this:
|
75
|
+
|
76
|
+
bakker -m remove *
|
77
|
+
|
78
|
+
Then the result would have looked like this:
|
79
|
+
|
80
|
+
demo1
|
81
|
+
demo2
|
82
|
+
demo3
|
83
|
+
|
84
|
+
Bakker also includes a verbose mode which will inform you of any file transfer
|
85
|
+
in the console:
|
86
|
+
|
87
|
+
bakker -v config.ini
|
88
|
+
|
89
|
+
You can specify default values for extension, action, mode and even for the
|
90
|
+
verbose mode by using environment variables. Notice that you can still override
|
91
|
+
these by using commandline switches. A list of the variables:
|
92
|
+
|
93
|
+
* BAKKER_MODE
|
94
|
+
* BAKKER_ACTION
|
95
|
+
* BAKKER_EXTENSION
|
96
|
+
* BAKKER_VERBOSE
|
97
|
+
|
98
|
+
=== Library
|
99
|
+
|
100
|
+
Load the gem:
|
101
|
+
|
102
|
+
require 'bakker'
|
103
|
+
|
104
|
+
Call Bakker:
|
105
|
+
|
106
|
+
Bakker.process('config.ini', '.backup', :add, :copy)
|
107
|
+
|
108
|
+
== REQUIREMENTS:
|
109
|
+
|
110
|
+
* user-choices (for commandline tool only)
|
111
|
+
* rspec (for testing only)
|
112
|
+
* sys-uname (for testing only)
|
113
|
+
|
114
|
+
== INSTALL:
|
115
|
+
|
116
|
+
* gem install bakker
|
117
|
+
* gem install user-choices (only for commandline tool)
|
118
|
+
|
119
|
+
== LICENSE:
|
120
|
+
|
121
|
+
Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
122
|
+
|
123
|
+
This file is part of Bakker.
|
124
|
+
|
125
|
+
Bakker is free software: you can redistribute it and/or modify
|
126
|
+
it under the terms of the GNU General Public License as published by
|
127
|
+
the Free Software Foundation, either version 3 of the License, or
|
128
|
+
(at your option) any later version.
|
129
|
+
|
130
|
+
This program is distributed in the hope that it will be useful,
|
131
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
132
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
133
|
+
GNU General Public License for more details.
|
134
|
+
|
135
|
+
You should have received a copy of the GNU General Public License
|
136
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/bakker.rb'
|
6
|
+
|
7
|
+
Hoe.new('bakker', Bakker::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'aef'
|
9
|
+
p.developer('Alexander E. Fischer', 'aef@raxys.net')
|
10
|
+
p.extra_dev_deps = %w{user-choices sys-uname}
|
11
|
+
p.testlib = 'spec'
|
12
|
+
p.test_globs = ['spec/**/*_spec.rb']
|
13
|
+
end
|
14
|
+
|
15
|
+
# vim: syntax=Ruby
|
data/bin/bakker
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
4
|
+
#
|
5
|
+
# This file is part of Bakker.
|
6
|
+
#
|
7
|
+
# Bakker is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
# TODO: If user-choices patch gets accepted, use :one_way => true for --version
|
21
|
+
# TODO: If user-choices patch gets accepted, use :upcase for environment variables
|
22
|
+
|
23
|
+
# If library is not locally accessible, use gem to include it.
|
24
|
+
begin
|
25
|
+
require 'lib/bakker'
|
26
|
+
rescue LoadError
|
27
|
+
require 'rubygems'
|
28
|
+
require 'bakker'
|
29
|
+
end
|
30
|
+
|
31
|
+
# User friendly message if user-choices is not available
|
32
|
+
begin
|
33
|
+
require 'user-choices'
|
34
|
+
rescue LoadError
|
35
|
+
warn "This command needs the user-choices gem to be installed.\n\nSolution: gem install user-choices"
|
36
|
+
exit false
|
37
|
+
end
|
38
|
+
|
39
|
+
# Application class for commandline interface
|
40
|
+
class Bakker::Application < UserChoices::Command
|
41
|
+
include UserChoices
|
42
|
+
|
43
|
+
# Prepare configuration sources
|
44
|
+
def add_sources(builder)
|
45
|
+
builder.add_source(CommandLineSource, :usage,
|
46
|
+
"Usage: #$PROGRAM_NAME [options] files\n\n",
|
47
|
+
"You can set the default behavior through environment variables:\n",
|
48
|
+
"BAKKER_MODE (#{Bakker::MODES.join(', ')}. Default: #{Bakker::MODES.first})",
|
49
|
+
"BAKKER_ACTION (#{Bakker::ACTIONS.join(', ')}. Default: #{Bakker::ACTIONS.first})",
|
50
|
+
'BAKKER_EXTENSION (Default: .bak)',
|
51
|
+
"BAKKER_VERBOSE (true, false. Default: false)\n"
|
52
|
+
)
|
53
|
+
|
54
|
+
# Hopefully possible with next release of user-choices
|
55
|
+
# builder.add_source(ExtendedEnvironmentSource, :upcase, :with_prefix, 'BAKKER_')
|
56
|
+
|
57
|
+
builder.add_source(EnvironmentSource, :mapping,
|
58
|
+
:mode => 'BAKKER_MODE',
|
59
|
+
:action => 'BAKKER_ACTION',
|
60
|
+
:extension => 'BAKKER_EXTENSION',
|
61
|
+
:verbose => 'BAKKER_VERBOSE'
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Define configuration options
|
66
|
+
def add_choices(builder)
|
67
|
+
builder.add_choice(:mode, :type => Bakker::MODES.map{|item| item.to_s}, :default => Bakker::MODES.first.to_s) do |cli|
|
68
|
+
cli.uses_option('-m', '--mode MODE',
|
69
|
+
"Processing mode. Can be one of: #{Bakker::MODES.join(', ')}. " +
|
70
|
+
"Default: #{Bakker::MODES.first}")
|
71
|
+
end
|
72
|
+
|
73
|
+
builder.add_choice(:action, :type => Bakker::ACTIONS.map{|item| item.to_s}, :default => Bakker::ACTIONS.first.to_s) do |cli|
|
74
|
+
cli.uses_option('-a', '--action ACTION',
|
75
|
+
"Filesystem action. Can be one of: #{Bakker::ACTIONS.join(', ')}. " +
|
76
|
+
"Default: #{Bakker::ACTIONS.first}")
|
77
|
+
end
|
78
|
+
|
79
|
+
builder.add_choice(:extension, :default => Bakker::DEFAULT_EXTENSION) do |cli|
|
80
|
+
cli.uses_option('-e', '--extension EXTENSION',
|
81
|
+
"Suffix to be added/removed"
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
builder.add_choice(:verbose, :type => :boolean, :default => false) do |cli|
|
86
|
+
cli.uses_switch('-v', '--verbose', 'Log all actions to console')
|
87
|
+
end
|
88
|
+
|
89
|
+
builder.add_choice(:version, :default => false, :type => :boolean) do |cli|
|
90
|
+
cli.uses_switch('--version', 'Display version and licensing information')
|
91
|
+
end
|
92
|
+
|
93
|
+
builder.add_choice(:filenames) {|cli| cli.uses_arglist }
|
94
|
+
end
|
95
|
+
|
96
|
+
# Main program
|
97
|
+
def execute
|
98
|
+
if @user_choices[:version]
|
99
|
+
klass = Bakker
|
100
|
+
puts "\n#{klass.name} #{klass::VERSION}"
|
101
|
+
puts DATA.read; exit
|
102
|
+
end
|
103
|
+
|
104
|
+
if @user_choices[:filenames].empty?
|
105
|
+
warn 'No files given'; exit false
|
106
|
+
else
|
107
|
+
@user_choices[:filenames].each do |filename|
|
108
|
+
begin
|
109
|
+
Bakker.process(filename, @user_choices[:extension], @user_choices[:mode].to_sym,
|
110
|
+
@user_choices[:action].to_sym, { :verbose => @user_choices[:verbose] })
|
111
|
+
rescue BakkerWarning
|
112
|
+
warn "Ignoring #{filename}: #$!"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
S4tUtils.with_pleasant_exceptions {Bakker::Application.new.execute}
|
120
|
+
|
121
|
+
__END__
|
122
|
+
|
123
|
+
Project: https://rubyforge.org/projects/aef/
|
124
|
+
RDoc: http://aef.rubyforge.org/bakker/
|
125
|
+
|
126
|
+
Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
127
|
+
|
128
|
+
Bakker is free software: you can redistribute it and/or modify
|
129
|
+
it under the terms of the GNU General Public License as published by
|
130
|
+
the Free Software Foundation, either version 3 of the License, or
|
131
|
+
(at your option) any later version.
|
132
|
+
|
133
|
+
This program is distributed in the hope that it will be useful,
|
134
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
135
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
136
|
+
GNU General Public License for more details.
|
137
|
+
|
138
|
+
You should have received a copy of the GNU General Public License
|
139
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/lib/bakker.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Copyright 2009 Alexander E. Fischer <aef@raxys.net>
|
2
|
+
#
|
3
|
+
# This file is part of Bakker.
|
4
|
+
#
|
5
|
+
# Bakker is free software: you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or
|
8
|
+
# (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This program is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13
|
+
# GNU General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU General Public License
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
17
|
+
|
18
|
+
require 'fileutils'
|
19
|
+
|
20
|
+
class BakkerWarning < StandardError; end
|
21
|
+
|
22
|
+
module Bakker
|
23
|
+
VERSION = '1.0.0'
|
24
|
+
DEFAULT_EXTENSION = '.bak'
|
25
|
+
MODES = [:toggle, :add, :remove]
|
26
|
+
ACTIONS = [:move, :copy]
|
27
|
+
|
28
|
+
# For possible options see FileUtils methods cp() and mv()
|
29
|
+
def self.process(filename, extension = DEFAULT_EXTENSION, mode = MODES.first, action = ACTIONS.first, options = {})
|
30
|
+
raise ArgumentError, 'Action can only be :copy or :move.' unless ACTIONS.include?(action)
|
31
|
+
raise ArgumentError, 'Mode can only be :toggle, :add or :remove.' unless MODES.include?(mode)
|
32
|
+
|
33
|
+
# Regex used for determining if an extension should be added or removed
|
34
|
+
regexp = /#{Regexp.escape(extension)}$/
|
35
|
+
|
36
|
+
# Find out both the basic file name and the extended file name for every
|
37
|
+
# situation possible
|
38
|
+
filename_without_extension = filename.gsub(regexp, '')
|
39
|
+
filename_with_extension = filename_without_extension + extension
|
40
|
+
|
41
|
+
# Check both cases for existence for further processing
|
42
|
+
without_exists = File.exists?(filename_without_extension)
|
43
|
+
with_exists = File.exists?(filename_with_extension)
|
44
|
+
|
45
|
+
# Error if both unextended and extended files or none of them exist
|
46
|
+
#
|
47
|
+
# The mode variable contains symbols :copy or :move which correspond to
|
48
|
+
# methods of class FileUtils which are invoked through the send() method.
|
49
|
+
if without_exists and with_exists
|
50
|
+
raise BakkerWarning, "Both #{filename_without_extension} and #{filename_with_extension} already exist."
|
51
|
+
elsif without_exists and not with_exists
|
52
|
+
if [:toggle, :add].include?(mode)
|
53
|
+
FileUtils.send(action, filename_without_extension, filename_with_extension, options)
|
54
|
+
filename_with_extension
|
55
|
+
else
|
56
|
+
filename_without_extension
|
57
|
+
end
|
58
|
+
elsif not without_exists and with_exists
|
59
|
+
if [:toggle, :remove].include?(mode)
|
60
|
+
FileUtils.send(action, filename_with_extension, filename_without_extension, options)
|
61
|
+
filename_without_extension
|
62
|
+
else
|
63
|
+
filename_with_extension
|
64
|
+
end
|
65
|
+
else
|
66
|
+
raise BakkerWarning, "Neither #{filename_without_extension} nor #{filename_with_extension} found."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|