philiprehberger-pathname_kit 0.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3d307f3b4309bc786d63332bc60c097aae61cfed960a3a00d0a354435426fdd1
4
+ data.tar.gz: 2a650ca32af727f254b2a8b0bb44016067e10f975f4510098e713c55299e4c13
5
+ SHA512:
6
+ metadata.gz: bbd7f36bbf1efc5c9e76a5429d448ad4b132ffe93d7bd727bf74fb9f92f8a0c88ea8513a6b2a41c7f0ed2fc257b419c935ab6670d3c14df3e014bf8dc69a2c69
7
+ data.tar.gz: 8b6909b94b63402b60255479bf51aa1e2d0acfaf0f57548f778fb6c408832593fdc9b13049447b9ed2b0cce23535a7b0f91fa35ee4f7a4bc9777cc132be34d4d
data/CHANGELOG.md ADDED
@@ -0,0 +1,20 @@
1
+ # Changelog
2
+
3
+ All notable changes to this gem will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-03-22
11
+
12
+ ### Added
13
+ - Initial release
14
+ - Atomic file writes with temp file and rename
15
+ - Directory creation with ensure_directory
16
+ - Safe file deletion that returns success/failure
17
+ - Glob-based file finding
18
+ - Tempfile helper with automatic cleanup
19
+ - File touch with parent directory creation
20
+ - Line counting for files
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 philiprehberger
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # philiprehberger-pathname_kit
2
+
3
+ [![Tests](https://github.com/philiprehberger/rb-pathname-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/philiprehberger/rb-pathname-kit/actions/workflows/ci.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/philiprehberger-pathname_kit.svg)](https://rubygems.org/gems/philiprehberger-pathname_kit)
5
+ [![License](https://img.shields.io/github/license/philiprehberger/rb-pathname-kit)](LICENSE)
6
+
7
+ Pathname extensions for atomic write, safe delete, and common file operations
8
+
9
+ ## Requirements
10
+
11
+ - Ruby >= 3.1
12
+
13
+ ## Installation
14
+
15
+ Add to your Gemfile:
16
+
17
+ ```ruby
18
+ gem 'philiprehberger-pathname_kit'
19
+ ```
20
+
21
+ Or install directly:
22
+
23
+ ```bash
24
+ gem install philiprehberger-pathname_kit
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```ruby
30
+ require 'philiprehberger/pathname_kit'
31
+
32
+ Philiprehberger::PathnameKit.atomic_write('config.yml') do |f|
33
+ f.write('key: value')
34
+ end
35
+ ```
36
+
37
+ ### Atomic Write
38
+
39
+ ```ruby
40
+ Philiprehberger::PathnameKit.atomic_write('/path/to/file.txt') do |f|
41
+ f.write('safe content')
42
+ end
43
+ ```
44
+
45
+ ### Directory and File Operations
46
+
47
+ ```ruby
48
+ Philiprehberger::PathnameKit.ensure_directory('/path/to/nested/dir')
49
+ Philiprehberger::PathnameKit.touch('/path/to/file.txt')
50
+ Philiprehberger::PathnameKit.safe_delete('/path/to/old.txt') # => true or false
51
+ ```
52
+
53
+ ### Finding and Counting
54
+
55
+ ```ruby
56
+ files = Philiprehberger::PathnameKit.find('/src/**/*.rb')
57
+ count = Philiprehberger::PathnameKit.line_count('/path/to/file.rb')
58
+ ```
59
+
60
+ ### Tempfile Helper
61
+
62
+ ```ruby
63
+ Philiprehberger::PathnameKit.tempfile('.csv') do |path|
64
+ File.write(path, 'a,b,c')
65
+ # temp file is cleaned up automatically
66
+ end
67
+ ```
68
+
69
+ ## API
70
+
71
+ | Method | Description |
72
+ |--------|-------------|
73
+ | `.atomic_write(path) { \|f\| }` | Write to a temp file then rename atomically |
74
+ | `.ensure_directory(path)` | Create directory and all parents if needed |
75
+ | `.safe_delete(path)` | Delete a file, returning true if deleted |
76
+ | `.find(glob)` | Find files matching a glob pattern |
77
+ | `.tempfile(ext) { \|path\| }` | Create a temp file and yield its path |
78
+ | `.touch(path)` | Create or update a file's modification time |
79
+ | `.line_count(path)` | Count the number of lines in a file |
80
+
81
+ ## Development
82
+
83
+ ```bash
84
+ bundle install
85
+ bundle exec rspec # Run tests
86
+ bundle exec rubocop # Check code style
87
+ ```
88
+
89
+ ## License
90
+
91
+ MIT
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Philiprehberger
4
+ module PathnameKit
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,119 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'pathname_kit/version'
4
+ require 'fileutils'
5
+ require 'tempfile'
6
+ require 'pathname'
7
+
8
+ module Philiprehberger
9
+ module PathnameKit
10
+ class Error < StandardError; end
11
+
12
+ # Write content atomically by writing to a temp file then renaming.
13
+ #
14
+ # @param path [String] the file path to write to
15
+ # @yield [IO] the temporary file to write to
16
+ # @return [void]
17
+ # @raise [Error] if path is nil or empty
18
+ def self.atomic_write(path)
19
+ raise Error, 'path cannot be nil' if path.nil?
20
+ raise Error, 'path cannot be empty' if path.to_s.empty?
21
+
22
+ dir = File.dirname(path)
23
+ ensure_directory(dir)
24
+
25
+ temp = Tempfile.new(['atomic', File.extname(path)], dir)
26
+ begin
27
+ yield temp
28
+ temp.close
29
+ FileUtils.mv(temp.path, path)
30
+ rescue StandardError
31
+ temp.close
32
+ temp.unlink
33
+ raise
34
+ end
35
+ end
36
+
37
+ # Ensure a directory exists, creating it and all parents if needed.
38
+ #
39
+ # @param path [String] the directory path
40
+ # @return [void]
41
+ # @raise [Error] if path is nil or empty
42
+ def self.ensure_directory(path)
43
+ raise Error, 'path cannot be nil' if path.nil?
44
+ raise Error, 'path cannot be empty' if path.to_s.empty?
45
+
46
+ FileUtils.mkdir_p(path)
47
+ end
48
+
49
+ # Safely delete a file, returning true if deleted and false if not found.
50
+ #
51
+ # @param path [String] the file path to delete
52
+ # @return [Boolean] true if the file was deleted
53
+ # @raise [Error] if path is nil or empty
54
+ def self.safe_delete(path)
55
+ raise Error, 'path cannot be nil' if path.nil?
56
+ raise Error, 'path cannot be empty' if path.to_s.empty?
57
+
58
+ return false unless File.exist?(path)
59
+
60
+ File.delete(path)
61
+ true
62
+ end
63
+
64
+ # Find files matching a glob pattern.
65
+ #
66
+ # @param glob [String] the glob pattern
67
+ # @return [Array<String>] matching file paths
68
+ # @raise [Error] if glob is nil or empty
69
+ def self.find(glob)
70
+ raise Error, 'glob cannot be nil' if glob.nil?
71
+ raise Error, 'glob cannot be empty' if glob.to_s.empty?
72
+
73
+ Dir.glob(glob).sort
74
+ end
75
+
76
+ # Create a temporary file with a given extension and yield its path.
77
+ #
78
+ # @param ext [String] the file extension (e.g. '.txt')
79
+ # @yield [String] the temporary file path
80
+ # @return [Object] the block return value
81
+ def self.tempfile(ext = '.tmp')
82
+ temp = Tempfile.new(['tmp', ext])
83
+ begin
84
+ yield temp.path
85
+ ensure
86
+ temp.close
87
+ temp.unlink
88
+ end
89
+ end
90
+
91
+ # Touch a file, creating it if it does not exist and updating its mtime.
92
+ #
93
+ # @param path [String] the file path
94
+ # @return [void]
95
+ # @raise [Error] if path is nil or empty
96
+ def self.touch(path)
97
+ raise Error, 'path cannot be nil' if path.nil?
98
+ raise Error, 'path cannot be empty' if path.to_s.empty?
99
+
100
+ dir = File.dirname(path)
101
+ ensure_directory(dir)
102
+ FileUtils.touch(path)
103
+ end
104
+
105
+ # Count the number of lines in a file.
106
+ #
107
+ # @param path [String] the file path
108
+ # @return [Integer] the number of lines
109
+ # @raise [Error] if path is nil or empty
110
+ # @raise [Error] if the file does not exist
111
+ def self.line_count(path)
112
+ raise Error, 'path cannot be nil' if path.nil?
113
+ raise Error, 'path cannot be empty' if path.to_s.empty?
114
+ raise Error, "file not found: #{path}" unless File.exist?(path)
115
+
116
+ File.readlines(path).size
117
+ end
118
+ end
119
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: philiprehberger-pathname_kit
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Philip Rehberger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-03-22 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Pathname utility library providing atomic writes, safe deletes, directory
14
+ creation, glob-based file finding, tempfile helpers, touch, and line counting. All
15
+ operations handle edge cases and cleanup gracefully.
16
+ email:
17
+ - me@philiprehberger.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - CHANGELOG.md
23
+ - LICENSE
24
+ - README.md
25
+ - lib/philiprehberger/pathname_kit.rb
26
+ - lib/philiprehberger/pathname_kit/version.rb
27
+ homepage: https://github.com/philiprehberger/rb-pathname-kit
28
+ licenses:
29
+ - MIT
30
+ metadata:
31
+ homepage_uri: https://github.com/philiprehberger/rb-pathname-kit
32
+ source_code_uri: https://github.com/philiprehberger/rb-pathname-kit
33
+ changelog_uri: https://github.com/philiprehberger/rb-pathname-kit/blob/main/CHANGELOG.md
34
+ bug_tracker_uri: https://github.com/philiprehberger/rb-pathname-kit/issues
35
+ rubygems_mfa_required: 'true'
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 3.1.0
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubygems_version: 3.5.22
52
+ signing_key:
53
+ specification_version: 4
54
+ summary: Pathname extensions for atomic write, safe delete, and common file operations
55
+ test_files: []