summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-02-26 12:04:16 +0200
committerPaul Buetow <paul@buetow.org>2025-02-26 12:04:16 +0200
commit90ddeff0cf134240659003796e28708f046a5030 (patch)
tree2ba2cf44f94acba559397f6f0734163be0bc3a45
parentb394011ce33bd6116bb7d27520d5adea27310862 (diff)
can change owner of files and dirs
-rw-r--r--TODO.md19
-rw-r--r--lib/dslkeywords/file.rb46
-rw-r--r--test/lib/dslkeywords/mode_test.rb26
3 files changed, 75 insertions, 16 deletions
diff --git a/TODO.md b/TODO.md
index 0c65e59..385f2e2 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,12 +1,7 @@
# TODO
-* Support for file modes (owner, chmod)
- Test the mode
-* Recursively install a directory (rsync?)
-* User and group management
- * Fedora
- * FreeBSD
- * OpenBSD
+* Recursively install a directory (rsync? custom file copier?)
+* Change permissions of a directory recursively
* CRON jobs
* Fedora
* FreeBSD
@@ -22,3 +17,13 @@
* Homebrew (macOS)
* Make a gem out of rcm
* Use rakelib and split up rakefiles
+* User and group management
+ * Fedora
+ * add user
+ * remove user
+ * add group to user
+ * remove group from user
+ * add group
+ * remove group
+ * FreeBSD
+ * OpenBSD
diff --git a/lib/dslkeywords/file.rb b/lib/dslkeywords/file.rb
index c1f55d3..41fcf16 100644
--- a/lib/dslkeywords/file.rb
+++ b/lib/dslkeywords/file.rb
@@ -59,6 +59,8 @@ module RCM
def path(file_path = nil) = file_path.nil? ? @file_path : @file_path = file_path
def without(what) = @without_backup = validate(__method__, what.to_sym, :backup) == :backup
def mode(what) = @mode = what
+ def owner(what) = @owner = what
+ def group(what) = @group = what
def evaluate!
unless super
@@ -78,12 +80,12 @@ module RCM
protected
- def mode!(file_path = path)
- return if !::File.exist?(file_path) || @mode.nil?
+ def permissions!(file_path = path)
+ return unless ::File.exist?(file_path)
- dry? "Setting mode of #{file_path} to #{@mode}" do
- FileUtils.chmod(@mode, file_path)
- end
+ stat = ::File.stat(file_path)
+ set_mode!(stat)
+ set_owner!(stat)
end
# Validate whether we can use this up in this context or not
@@ -112,6 +114,32 @@ module RCM
parent_dir = ::File.dirname(parent_dir)
end
end
+
+ private
+
+ def set_mode!(stat, file_path = path)
+ return if @mode.nil?
+
+ current_mode = stat.mode.to_s(8).split('')[-4..-1].join.to_i(8)
+ return unless current_mode != @mode
+
+ dry? "Changing mode of #{file_path} to #{@mode}" do
+ FileUtils.chmod(@mode, file_path)
+ end
+ end
+
+ def set_owner!(stat, file_path = path)
+ return if @owner.nil? && @group.nil?
+
+ current_owner = Etc.getpwuid(stat.uid)
+ current_group = Etc.getgrgid(stat.gid)
+
+ return if (@owner.nil? || @owner == current_owner) && (@group.nil? || @group == current_group)
+
+ dry? "Changing owner of #{file_path} to #{@owner || ''}:#{@group || ''}" do
+ FileUtils.chown(@owner, @group, file_path)
+ end
+ end
end
# Base for File and Symlink
@@ -147,7 +175,7 @@ module RCM
write!(content)
ensure
- mode!
+ permissions!
end
private
@@ -207,7 +235,7 @@ module RCM
FileUtils.ln_sf(content, @file_path)
end
ensure
- mode!
+ permissions!
end
end
@@ -226,7 +254,7 @@ module RCM
FileUtils.touch(@file_path)
end
ensure
- mode!
+ permissions!
end
end
@@ -241,7 +269,7 @@ module RCM
evaluate_absent!
end
ensure
- mode!
+ permissions!
end
def evaluate_present!
diff --git a/test/lib/dslkeywords/mode_test.rb b/test/lib/dslkeywords/mode_test.rb
index 4102c74..a4bf099 100644
--- a/test/lib/dslkeywords/mode_test.rb
+++ b/test/lib/dslkeywords/mode_test.rb
@@ -46,4 +46,30 @@ class RCMModeTest < Minitest::Test
assert_equal 0o705, File.stat(DIR_PATH).mode.to_s(8).split('')[-4..-1].join.to_i(8)
assert_equal 0o777, File.stat(SYMLINK_TARGET_PATH).mode.to_s(8).split('')[-4..-1].join.to_i(8)
end
+
+ def test_chown
+ configure_from_scratch do
+ # Well, test only makes sense that it doesn't throw any exception, as test
+ # can't change files to other owners as test will likely run as non-root.
+ user_name = Etc.getlogin
+ group_name = Etc.getgrgid(Process.gid).name
+
+ touch FILE1_PATH do
+ owner user_name
+ group group_name
+ end
+ directory DIR_PATH do
+ owner user_name
+ group group_name
+ end
+
+ stat = File.stat(FILE1_PATH)
+ assert_equal user_name, Etc.getpwuid(stat.uid)
+ assert_equal group_name, Etc.getgrgid(stat.gid)
+
+ stat = File.stat(DIR_PATH)
+ assert_equal user_name, Etc.getpwuid(stat.uid)
+ assert_equal group_name, Etc.getgrgid(stat.gid)
+ end
+ end
end