rmtree 2.2.3

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 (3) hide show
  1. data/README +89 -0
  2. data/bin/rmtree +176 -0
  3. metadata +60 -0
data/README ADDED
@@ -0,0 +1,89 @@
1
+ NAME
2
+
3
+ rmtree - save and restore permissions of objects in a directory
4
+
5
+ SYNOPSIS
6
+
7
+ rmtree save [-C working_dir] [--files] [--dirs]
8
+ rmtree apply [-C working_dir] [--files] [--dirs] [--dry-run]
9
+ rmtree diff [-C working_dir] [--files] [--dirs]
10
+ rmtree load
11
+ rmtree help
12
+
13
+ DESCRIPTION
14
+
15
+ `rmtree` is a simple version of known tool `mtree` on *BSD system. The
16
+ primary purpose of the tool is to save some basic attributes of objects
17
+ in a directory to a text file and/or restore objects' properties from
18
+ a standard input of attributes.
19
+
20
+ The tool only works on file system that supports following attributes:
21
+
22
+ - File mode (like 0644 on Linux)
23
+ - File owner
24
+ - File group
25
+
26
+ When the action `save` is used, the tool will scan the working directory
27
+ for all files and directories, and read their properties and print in
28
+ YAML format -- the readable format used by the action `apply` (or `load`.)
29
+
30
+ EXAMPLES
31
+
32
+ To back up objects' attributes to a file
33
+
34
+ rmtree save -C /path/to/working/dir | gzip -9c > backup.gz
35
+
36
+ To restore file permissions
37
+
38
+ zcat backup.gz | rmtree apply -C /path/to/working/dir
39
+
40
+ Save and load at the same time
41
+
42
+ rmtree save -C /this/dir/ | rmtree apply -C /that/dir/
43
+
44
+ To compare this directory with another one
45
+
46
+ rmtree save -C /this/dir | rmtree diff -C /that/dir
47
+
48
+ OPTIONS
49
+
50
+ Actions
51
+
52
+ help Print some help messages
53
+ save Scan for objects' attributes
54
+ apply Apply attributes to objects in working directory
55
+ load Load attribute data and print to STDOUT
56
+ diff Compare STDIN with the working directory
57
+
58
+ Options
59
+
60
+ -d --dry-run Execute `apply` in dry-run mode
61
+
62
+ -C --directory Set the working directory. The program will change
63
+ to this directory before scanning/applying attributes.
64
+ Default: current directory
65
+
66
+ -F --files Only work on files. When being used with 'diff',
67
+ all directories in working directory are ignored.
68
+
69
+ -D --dirs Only work on directories. When being used with 'diff',
70
+ all regular files in working directory are ignored.
71
+
72
+ --full-path Print absolute path when 'saving'. As the output has
73
+ the full paths, you may use the output for the action
74
+ 'apply' without specifying the working directory.
75
+ (This also means that you can't apply the output to
76
+ another directory.) By default, the program prints
77
+ the relative paths.
78
+
79
+ -h --help Print help message
80
+
81
+ INSTALLATION
82
+
83
+ This ruby tool requires the rubygem 'slop' (for arguments parsing.)
84
+ To build a rubygem, try `gem build rmtree.gemspec`.
85
+
86
+ To use this tool, simply make it executable (by `chmod 755 rmtree.rb`.)
87
+ If the rubygem 'rmtree-x.y.z' was installed, the binary can be found
88
+ in the binary directory of your gem environment. (Please run the command
89
+ `gem env | grep EXECUTABLE` for details.)
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Purpose: Backup & Restore attributes of objects in a directory
4
+ # Author : Anh K. Huynh
5
+ # License: GPL2
6
+ # Date : 2012 May 15th
7
+
8
+ begin
9
+ require 'rubygems'
10
+ require 'slop'
11
+ require 'find'
12
+ require 'fileutils'
13
+ require 'yaml'
14
+ rescue LoadError => e
15
+ STDERR.puts ":: Error: Can't load some of libraries with error '#{e}'"
16
+ exit(1)
17
+ end
18
+
19
+ # Raise and message and exit
20
+ def _raise(msg)
21
+ STDERR.puts(":: #{msg}")
22
+ exit(1)
23
+ end
24
+
25
+ def _chdir(cwd, options)
26
+ begin
27
+ if options[:verbose]
28
+ STDERR.puts(":: Set working directory to #{cwd}")
29
+ end
30
+ FileUtils.chdir(cwd)
31
+ rescue => e
32
+ _raise "Error: Can't set working directory #{cwd} with error '#{e}'"
33
+ end
34
+ end
35
+
36
+ # Scan a directory and print objects attributes
37
+ # * `source`: The source direction
38
+ # * `options`: Options for scanning
39
+ # FIXME: source may not work with working directory
40
+ def _fetch(options)
41
+ ret = []
42
+ path_prefix = options[:fullpath] ? "#{File.expand_path("./")}/" : ""
43
+ begin
44
+ Find.find("./") do |file|
45
+ next if file.match(/^\.\.?\/$/)
46
+ next if options[:files] && File.directory?(file)
47
+ next if options[:dirs] && File.file?(file)
48
+ begin
49
+ stat = File.stat(file)
50
+ ret << sprintf("%s%s:\n mode: %s\n uid: %s\n gid: %s",
51
+ path_prefix, file.slice(2,file.size), stat.mode.to_s(8), stat.uid, stat.gid)
52
+ rescue => e
53
+ ret << sprintf("%s%s:\n error: #{e}", path_prefix, file.slice(2,file.size))
54
+ end
55
+ end
56
+ rescue => e
57
+ _raise("Error in _fetch(#{source}): #{e}")
58
+ end
59
+ ret = ret.join("\n")
60
+ if options[:to_stdout]
61
+ puts ret
62
+ else
63
+ YAML.load(ret)
64
+ end
65
+ end
66
+
67
+ # Load YAML data from STDIN and return the hash
68
+ # FIXME: we should check the format of the input
69
+ def _load(options)
70
+ begin
71
+ yaml = YAML.load(STDIN.read)
72
+ rescue Psych::SyntaxError => e
73
+ _raise "Error: Can't load Rmtree data with error '#{e}'"
74
+ end
75
+ puts YAML.dump(yaml) if options[:to_stdout]
76
+ yaml
77
+ end
78
+
79
+ def _apply(yaml, options = nil)
80
+ yaml.each do |file, data|
81
+ next if options[:files] && File.directory?(file)
82
+ next if options[:dirs] && File.file?(file)
83
+ if not data["error"]
84
+ mode, uid, gid = data["mode"].to_s, data["uid"], data["gid"]
85
+ mode = mode.slice(mode.size - 4, mode.size)
86
+ if options[:dryrun]
87
+ puts "chown #{uid}:#{gid} '#{file}'" if uid or gid
88
+ puts "chmod #{mode} '#{file}'" # FIXME
89
+ else
90
+ begin
91
+ FileUtils.chown uid, gid, file if uid or gid
92
+ FileUtils.chmod mode.to_i(8), file # FIXME
93
+ rescue => e
94
+ STDERR.puts "Error: Can't apply attribute to file #{file}, error => '#{e}'"
95
+ end
96
+ end
97
+ else
98
+ # Print some warning message
99
+ end
100
+ end
101
+ end
102
+
103
+ # Compare STDIN with current working directory
104
+ def _diff(this, that, options)
105
+ that = _fetch(options) unless that
106
+ this_keys = this.keys
107
+ that_keys = that.keys
108
+
109
+ common_keys = this_keys & that_keys
110
+ this_only = this_keys - common_keys
111
+ that_only = that_keys - common_keys
112
+
113
+ this_only.each {|k| puts "Only in source: #{k}" }
114
+ that_only.each {|k| puts "Only in working directory: #{k}" }
115
+ common_keys.each do |k|
116
+ this_data = %w{mode uid gid}.map{|v| this[k][v]}
117
+ that_data = %w{mode uid gid}.map{|v| that[k][v]}
118
+ next if this_data == that_data
119
+ puts "#{k}:"
120
+ puts "< #{this_data.join(", ")}"
121
+ puts "> #{that_data.join(", ")}"
122
+ end
123
+ end
124
+
125
+ ########################################################################
126
+ # main routine
127
+ ########################################################################
128
+
129
+ valid_actions = %w{help save load apply diff}
130
+
131
+ action = ARGV.shift
132
+ _raise "Usage: rmtree #{valid_actions.join("|")} <options>" unless valid_actions.include?(action)
133
+
134
+ options = {:files => false, :dirs => false}
135
+
136
+ begin
137
+ opts = Slop.parse do
138
+ banner "Backup, restore or compare attributes of objects in two directories.
139
+ Syntax: rmtree.rb #{valid_actions.join("|")} [options]\n"
140
+
141
+ on "C", "directory=",'Set working directory'
142
+ on "F", "files", 'Only work on files'
143
+ on "D", "dirs", 'Only work on directories'
144
+ on "d", "dry-run", 'Apply with dry-run mode'
145
+ on "full-path", 'Print absolute paths when "saving"'
146
+ on "v", "verbose", 'Verbose output'
147
+ on "h", "help", 'Print help message'
148
+ end
149
+ rescue Slop::MissingArgumentError => e
150
+ _raise "Error: #{e}"
151
+ end
152
+
153
+ if opts.present?(:help) or action == "help"
154
+ puts opts.help
155
+ exit(0)
156
+ end
157
+
158
+ # Set up file options
159
+ _raise "Error: You can only use one of two options `--files`, `--dirs`" \
160
+ if opts.present?(:files) and opts.present?(:dirs)
161
+
162
+ options.merge!(:files => true) if opts.present?(:files)
163
+ options.merge!(:dirs => true) if opts.present?(:dirs)
164
+ options.merge!(:dryrun => true) if opts.present?(:"dry-run")
165
+ options.merge!(:verbose => true) if opts.present?(:verbose)
166
+ options.merge!(:fullpath => true) if opts.present?(:"full-path")
167
+
168
+ cwd = opts.present?(:directory) ? opts[:directory] : "./"
169
+ _chdir(cwd, options)
170
+
171
+ case action
172
+ when "save" then _fetch(options.merge(:to_stdout => true))
173
+ when "diff" then _diff(_load(options), nil, options)
174
+ when "load" then _load(options.merge(:to_stdout => true))
175
+ when "apply" then _apply(_load(options), options)
176
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rmtree
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.2.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Anh K. Huynh
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: slop
16
+ requirement: &9582440 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *9582440
25
+ description: Backup & Restore attributes of objects in a directory
26
+ email: kyanh@viettug.org
27
+ executables:
28
+ - rmtree
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - README
33
+ - bin/rmtree
34
+ homepage: https://github.com/icy/rmtree
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project:
54
+ rubygems_version: 1.8.16
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: ! '`rmtree` is a simple version of known tool `mtree` on *BSD system. The
58
+ primary purpose of the tool is to save some basic attributes of objects in a directory
59
+ to a text file and/or restore objects'' properties from a standard input of attributes.'
60
+ test_files: []