rmtree 2.2.3

Sign up to get free protection for your applications and to get access to all the features.
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: []