aef-bakker 1.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.
data/History.txt ADDED
@@ -0,0 +1,23 @@
1
+ === 1.1.0 / 2009-04-05
2
+
3
+ * 1 major enhancement
4
+
5
+ * Namespaced into module Aef
6
+
7
+ * 5 minor enhancements
8
+
9
+ * Better metadata for gem
10
+ * Test refactoring
11
+ * Minor refactorings
12
+ * Improved documentation
13
+ * Added test for --version command
14
+
15
+ * 1 minor bugfix
16
+
17
+ * Fixed some bugs related to Ruby 1.8.6
18
+
19
+ === 1.0.0 / 2009-03-01
20
+
21
+ * 1 major enhancement
22
+
23
+ * Birthday!
data/Manifest.txt ADDED
@@ -0,0 +1,9 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ COPYING.txt
5
+ Rakefile
6
+ bin/bakker
7
+ lib/bakker.rb
8
+ lib/bakker/bakker.rb
9
+ spec/bakker_spec.rb
data/README.rdoc ADDED
@@ -0,0 +1,206 @@
1
+ = Bakker
2
+
3
+ * Project: https://rubyforge.org/projects/aef/
4
+ * RDoc: http://aef.rubyforge.org/bakker/
5
+ * Github: http://github.com/aef/bakker/
6
+
7
+ == DESCRIPTION:
8
+
9
+ Bakker is a Ruby library and commandline tool to help with simple task of
10
+ renaming or copying files for quick backup purposes. For instance by creating
11
+ a copy of a list of files while adding .bak to the copies filenames. Bakker
12
+ gives you control over the extension to be added to or removed from the file
13
+ and whether it should be moved or copied.
14
+
15
+ == FEATURES/PROBLEMS:
16
+
17
+ * Usable as library and commandline tool
18
+ * Tested and fully working on:
19
+ * Ubuntu Linux 8.10 i386_64 (Ruby 1.8.7 and 1.9.1p0)
20
+ * Debian GNU/Linux 4.0 i386 (Ruby 1.8.6)
21
+ * On Windows XP i386 (Ruby 1.8.6)
22
+ * On Windows XP i386 (Ruby 1.8.6) there were some problems testing the
23
+ environment variable choices. Two tests are failing but the programs seems
24
+ to work correctly. If anyone finds the problem, please contact me.
25
+ * The commandline tool doesn't work with Ruby 1.9.x because the user-choices gem
26
+ is not yet updated. A patch is available here:
27
+ https://rubyforge.org/tracker/index.php?func=detail&aid=24307&group_id=4192&atid=16176
28
+
29
+ == SYNOPSIS:
30
+
31
+ === Commandline
32
+
33
+ The following command renames config.ini to config.ini.bak. You can type the
34
+ same command a second time to revert the action:
35
+
36
+ bakker config.ini
37
+
38
+ Instead of renaming you can create a copy of config.xml by using the following
39
+ command:
40
+
41
+ bakker -a copy config.ini
42
+
43
+ To change the extension which will be appended or removed from the filename use
44
+ the following command:
45
+
46
+ bakker -e .backup
47
+
48
+ In a directory with the follwing contents:
49
+
50
+ demo1
51
+ demo2.bak
52
+ demo3.bak
53
+
54
+ if you use the command:
55
+
56
+ bakker *
57
+
58
+ you get the following list of files (because by default Bakker toggles the
59
+ extension):
60
+
61
+ demo1.bak
62
+ demo2
63
+ demo3
64
+
65
+ if you now want every file in the folder to have a .bak extension use the
66
+ following command:
67
+
68
+ bakker -m add *
69
+
70
+ the result will look like this:
71
+
72
+ demo1.bak
73
+ demo2.bak
74
+ demo3.bak
75
+
76
+ Instead of using the add-mode you could have used the remove-mode like this:
77
+
78
+ bakker -m remove *
79
+
80
+ Then the result would have looked like this:
81
+
82
+ demo1
83
+ demo2
84
+ demo3
85
+
86
+ Bakker also includes a verbose mode which will inform you of any file transfer
87
+ in the console:
88
+
89
+ bakker -v config.ini
90
+
91
+ You can specify default values for extension, action, mode and even for the
92
+ verbose mode by using environment variables. Notice that you can still override
93
+ these by using commandline switches. A list of the variables:
94
+
95
+ * BAKKER_MODE
96
+ * BAKKER_ACTION
97
+ * BAKKER_EXTENSION
98
+ * BAKKER_VERBOSE
99
+
100
+ === Library
101
+
102
+ Load the gem:
103
+
104
+ require 'bakker'
105
+
106
+ Call Bakker:
107
+
108
+ Aef::Bakker.process('config.ini', '.backup', :add, :copy)
109
+
110
+ == REQUIREMENTS:
111
+
112
+ * rubygems
113
+
114
+ === Additional for commandline
115
+ * user-choices
116
+
117
+ === Additional for automated testing
118
+ * hoe
119
+ * rspec
120
+ * sys-uname
121
+
122
+ == INSTALL:
123
+
124
+ === Normal
125
+
126
+ gem install bakker
127
+
128
+ Additionally for the commandline tool:
129
+
130
+ gem install user-choices
131
+
132
+ === High security (recommended)
133
+
134
+ There is a high security installation option available through rubygems. It is
135
+ highly recommended over the normal installation, although it may be a bit less
136
+ comfortable. To use the installation method, you will need my public key, which
137
+ I use for cryptographic signatures on all my gems. You can find the public key
138
+ and more detailed verification information in the aef-certificates section of my
139
+ rubyforge project[https://rubyforge.org/frs/?group_id=7890&release_id=31749]
140
+
141
+ Add the key to your rubygems' trusted certificates by the following command:
142
+
143
+ gem cert --add aef.pem
144
+
145
+ Now you can install the gem while automatically verifying it's signature by the
146
+ following command:
147
+
148
+ gem install bakker --ignore-dependencies -P HighSecurity
149
+
150
+ Please notice that you will need other keys for dependent libraries, so you may
151
+ have to install dependencies manually.
152
+
153
+ === Automated testing
154
+
155
+ You can test this package through rspec on your system. First find the path
156
+ where the gem was installed to:
157
+
158
+ gem which bakker
159
+
160
+ Go into the root directory of the installed gem and run the following command
161
+ to start the test runner:
162
+
163
+ rake spec
164
+
165
+ On Windows systems you have to run the following instead:
166
+
167
+ spec spec/**/*_spec.rb
168
+
169
+ If something goes wrong you should be noticed through failing examples.
170
+
171
+ == DEVELOPMENT:
172
+
173
+ This software is developed in the source code management system git hosted
174
+ at github.com. You can download the most recent sourcecode through the following
175
+ command:
176
+
177
+ git clone git://github.com/aef/bakker.git
178
+
179
+ Help on making this software better is always very appreciated. If you want your
180
+ changes to be included in the official release, please send me a patch through
181
+ the project's tracker[https://rubyforge.org/tracker/?group_id=7890] at
182
+ rubyforge.org. You can generate a patch-file by the following command:
183
+
184
+ git diff > patch.diff
185
+
186
+ Please make sure to write tests for your changes and notice that I can't promise
187
+ to include your changes before reviewing them.
188
+
189
+ == LICENSE:
190
+
191
+ Copyright 2009 Alexander E. Fischer <aef@raxys.net>
192
+
193
+ This file is part of Bakker.
194
+
195
+ Bakker is free software: you can redistribute it and/or modify
196
+ it under the terms of the GNU General Public License as published by
197
+ the Free Software Foundation, either version 3 of the License, or
198
+ (at your option) any later version.
199
+
200
+ This program is distributed in the hope that it will be useful,
201
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
202
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
203
+ GNU General Public License for more details.
204
+
205
+ You should have received a copy of the GNU General Public License
206
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/bakker.rb'
6
+
7
+ Hoe.new('bakker', Aef::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 rspec sys-uname}
11
+ p.url = 'https://rubyforge.org/projects/aef/'
12
+ p.readme_file = 'README.rdoc'
13
+ p.extra_rdoc_files = %w{README.rdoc}
14
+ p.spec_extras = {
15
+ :rdoc_options => ['--main', 'README.rdoc', '--inline-source', '--line-numbers', '--title', 'Bakker']
16
+ }
17
+ end
18
+
19
+ # vim: syntax=Ruby
data/bin/bakker ADDED
@@ -0,0 +1,137 @@
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 Aef::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 (#{Aef::Bakker::MODES.join(', ')}. Default: #{Aef::Bakker::MODES.first})",
49
+ "BAKKER_ACTION (#{Aef::Bakker::ACTIONS.join(', ')}. Default: #{Aef::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 => Aef::Bakker::MODES.map{|item| item.to_s}, :default => Aef::Bakker::MODES.first.to_s) do |cli|
68
+ cli.uses_option('-m', '--mode MODE',
69
+ "Processing mode. Can be one of: #{Aef::Bakker::MODES.join(', ')}. " +
70
+ "Default: #{Aef::Bakker::MODES.first}")
71
+ end
72
+
73
+ builder.add_choice(:action, :type => Aef::Bakker::ACTIONS.map{|item| item.to_s}, :default => Aef::Bakker::ACTIONS.first.to_s) do |cli|
74
+ cli.uses_option('-a', '--action ACTION',
75
+ "Filesystem action. Can be one of: #{Aef::Bakker::ACTIONS.join(', ')}. " +
76
+ "Default: #{Aef::Bakker::ACTIONS.first}")
77
+ end
78
+
79
+ builder.add_choice(:extension, :default => Aef::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
+ # Manual option post processing
97
+ def postprocess_user_choices
98
+ version if @user_choices[:version]
99
+ end
100
+
101
+ # Version and licensing information output
102
+ def version
103
+ name = 'Bakker'
104
+ puts "#{name} #{Aef::Bakker::VERSION}"
105
+ puts
106
+ puts 'Project: https://rubyforge.org/projects/aef/'
107
+ puts "RDoc: http://aef.rubyforge.org/#{name.downcase}/"
108
+ puts "Github: http://github.com/aef/#{name.downcase}/"
109
+ puts
110
+ puts 'Copyright 2009 Alexander E. Fischer <aef@raxys.net>'
111
+ # Read and print licensing information from the top of this file
112
+ if Gem::Version.new(RUBY_VERSION) <= Gem::Version.new('1.8.6')
113
+ puts File.read(__FILE__).map{|line| line[2..-1]}[5..17]
114
+ else
115
+ puts File.read(__FILE__).lines.map{|line| line[2..-1]}[5..17]
116
+ end
117
+ exit
118
+ end
119
+
120
+ # Main program
121
+ def execute
122
+ if @user_choices[:filenames].empty?
123
+ warn 'No files given'; exit false
124
+ else
125
+ @user_choices[:filenames].each do |filename|
126
+ begin
127
+ Aef::Bakker.process(filename, @user_choices[:extension], @user_choices[:mode].to_sym,
128
+ @user_choices[:action].to_sym, { :verbose => @user_choices[:verbose] })
129
+ rescue Aef::BakkerWarning
130
+ warn "Ignoring #{filename}: #$!"
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ S4tUtils.with_pleasant_exceptions {Aef::Bakker::Application.new.execute}
data/lib/bakker.rb ADDED
@@ -0,0 +1,29 @@
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
+ # Namespace for projects of Alexander E. Fischer <aef@raxys.net>
19
+ #
20
+ # If you want to be able to simply type Example instead of Aef::Example to
21
+ # address classes in this namespace simply write the following before using the
22
+ # classes:
23
+ #
24
+ # include Aef
25
+ module Aef
26
+
27
+ end
28
+
29
+ require File.join(File.dirname(__FILE__), 'bakker/bakker')
@@ -0,0 +1,73 @@
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 Aef::BakkerWarning < StandardError; end
21
+
22
+ # Bakker is a Ruby library and commandline tool to help with simple task of
23
+ # renaming or copying files for quick backup purposes.
24
+ module Aef::Bakker
25
+ VERSION = '1.1.0'
26
+ DEFAULT_EXTENSION = '.bak'
27
+ MODES = [:toggle, :add, :remove]
28
+ ACTIONS = [:move, :copy]
29
+
30
+ module_function
31
+
32
+ # For possible options see FileUtils methods cp() and mv()
33
+ def process(filename, extension = DEFAULT_EXTENSION, mode = MODES.first, action = ACTIONS.first, options = {})
34
+ raise ArgumentError, 'Action can only be :copy or :move.' unless ACTIONS.include?(action)
35
+ raise ArgumentError, 'Mode can only be :toggle, :add or :remove.' unless MODES.include?(mode)
36
+
37
+ # Regex used for determining if an extension should be added or removed
38
+ regexp = /#{Regexp.escape(extension)}$/
39
+
40
+ # Find out both the basic file name and the extended file name for every
41
+ # situation possible
42
+ filename_without_extension = filename.gsub(regexp, '')
43
+ filename_with_extension = filename_without_extension + extension
44
+
45
+ # Check both cases for existence for further processing
46
+ without_exists = File.exists?(filename_without_extension)
47
+ with_exists = File.exists?(filename_with_extension)
48
+
49
+ # Error if both unextended and extended files or none of them exist
50
+ #
51
+ # The mode variable contains symbols :copy or :move which correspond to
52
+ # methods of class FileUtils which are invoked through the send() method.
53
+ if without_exists and with_exists
54
+ raise Aef::BakkerWarning, "Both #{filename_without_extension} and #{filename_with_extension} already exist."
55
+ elsif without_exists and not with_exists
56
+ if [:toggle, :add].include?(mode)
57
+ FileUtils.send(action, filename_without_extension, filename_with_extension, options)
58
+ filename_with_extension
59
+ else
60
+ filename_without_extension
61
+ end
62
+ elsif not without_exists and with_exists
63
+ if [:toggle, :remove].include?(mode)
64
+ FileUtils.send(action, filename_with_extension, filename_without_extension, options)
65
+ filename_without_extension
66
+ else
67
+ filename_with_extension
68
+ end
69
+ else
70
+ raise Aef::BakkerWarning, "Neither #{filename_without_extension} nor #{filename_with_extension} found."
71
+ end
72
+ end
73
+ end