bakker 1.0.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/Manifest.txt ADDED
@@ -0,0 +1,8 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ COPYING.txt
5
+ Rakefile
6
+ bin/bakker
7
+ lib/bakker.rb
8
+ spec/bakker_spec.rb
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