chore: add GetContent and PutContent methods to support/file#824
chore: add GetContent and PutContent methods to support/file#824almas-x merged 4 commits intogoravel:masterfrom almas-x:chore
Conversation
WalkthroughThe pull request introduces enhanced file handling capabilities in the Changes
Sequence DiagramsequenceDiagram
participant Client
participant PutContent
participant FileSystem
Client->>PutContent: Call with file path, content, options
PutContent->>PutContent: Initialize default options
PutContent->>PutContent: Apply provided options
PutContent->>FileSystem: Ensure directory exists
PutContent->>FileSystem: Open file with specified mode
PutContent->>FileSystem: Write content to file
FileSystem-->>PutContent: Return result
PutContent-->>Client: Return error (if any)
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #824 +/- ##
==========================================
+ Coverage 67.05% 67.17% +0.11%
==========================================
Files 147 148 +1
Lines 10394 10440 +46
==========================================
+ Hits 6970 7013 +43
- Misses 3051 3053 +2
- Partials 373 374 +1 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (5)
support/file/file.go (3)
14-34: LGTM! Consider enhancing documentation.The implementation follows the functional options pattern, which is idiomatic Go. The code is well-structured and clear.
Consider adding examples to the documentation to show how to use these options:
// WithMode sets the file mode for PutContent // // Example: // // err := PutContent("file.txt", "content", WithMode(0644))
53-54: Enhance deprecation notice with migration example.Good practice marking the function as deprecated while providing a migration path.
Consider enhancing the deprecation notice with a migration example:
// Deprecated: Use PutContent instead. // Before: Create("file.txt", "content") // After: PutContent("file.txt", "content")
Line range hint
1-1: Add package documentation.Consider adding package-level documentation to describe the package's purpose and common usage patterns.
Add at the top of the file:
// Package file provides utilities for file operations in the Goravel framework, // including reading, writing, and manipulating files with various options. package filesupport/file/file_test.go (2)
52-56: Use t.TempDir() for consistency.For consistency with TestCreate and better test isolation, consider using t.TempDir().
- pwd, _ := os.Getwd() - filePath := path.Join(pwd, "goravel/goravel.txt") + filePath := path.Join(t.TempDir(), "goravel.txt") assert.Nil(t, Create(filePath, `goravel`)) assert.Nil(t, Remove(filePath)) - assert.Nil(t, Remove(path.Join(pwd, "goravel")))
65-75: Use t.TempDir() for file testing.Consider using t.TempDir() for testing successful file operations instead of relying on an existing file.
func TestGetContent(t *testing.T) { // file not exists content, err := GetContent("files.go") assert.NotNil(t, err) assert.Empty(t, content) + // get content successfully - content, err = GetContent("../constant.go") + testFile := path.Join(t.TempDir(), "test.txt") + assert.NoError(t, PutContent(testFile, "const Version = 1")) + content, err = GetContent(testFile) assert.Nil(t, err) assert.NotNil(t, content) assert.Contains(t, content, "const Version") }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
support/file/file.go(2 hunks)support/file/file_test.go(3 hunks)
🧰 Additional context used
🪛 GitHub Check: codecov/patch
support/file/file.go
[warning] 173-174: support/file/file.go#L173-L174
Added lines #L173 - L174 were not covered by tests
[warning] 187-188: support/file/file.go#L187-L188
Added lines #L187 - L188 were not covered by tests
[warning] 193-194: support/file/file.go#L193-L194
Added lines #L193 - L194 were not covered by tests
🔇 Additional comments (3)
support/file/file.go (2)
41-47: LGTM! Good refactoring.The change to use GetContent improves code reusability and maintains consistent file reading behavior across the package.
149-157: LGTM! Clean implementation.The GetContent function provides a simple and effective way to read file contents with proper error handling.
support/file/file_test.go (1)
22-25: LGTM! Good test isolation.Using t.TempDir() improves test isolation and ensures proper cleanup.
hwbrzzl
left a comment
There was a problem hiding this comment.
Perfect 👍 Just one nitpick, and since you joined the Goravel organization, you can create the PR in repo directly instead of fork.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
support/file/file_test.go (2)
52-56: Consider using t.TempDir() for consistency.While using
path.Joinis good, consider usingt.TempDir()like inTestCreatefor better test isolation and consistency.- pwd, _ := os.Getwd() - filePath := path.Join(pwd, "goravel/goravel.txt") + filePath := path.Join(t.TempDir(), "goravel.txt")
65-75: Consider using t.TempDir() for test data.Instead of relying on existing files, create test files in a temporary directory for better test isolation and reliability.
- content, err := GetContent("files.go") + content, err := GetContent(path.Join(t.TempDir(), "nonexistent.txt")) - content, err = GetContent("../constant.go") + testFile := path.Join(t.TempDir(), "test.txt") + assert.NoError(t, PutContent(testFile, "const Version = \"1.0.0\"")) + content, err = GetContent(testFile)support/file/file.go (1)
98-106: Add documentation for GetContent.Consider adding a documentation comment explaining the function's purpose and error conditions.
+// GetContent reads the entire file and returns its content as a string. +// It returns an error if the file doesn't exist or cannot be read. func GetContent(file string) (string, error) {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
support/file/file.go(3 hunks)support/file/file_test.go(3 hunks)
🧰 Additional context used
🪛 GitHub Actions: Test
support/file/file_test.go
[error] 79-79: Test failure in TestPutContent: An error is expected but got nil.
[error] 83-83: Test failure in TestPutContent: An error is expected but got nil.
🪛 GitHub Check: codecov/patch
support/file/file.go
[warning] 165-166: support/file/file.go#L165-L166
Added lines #L165 - L166 were not covered by tests
🔇 Additional comments (5)
support/file/file_test.go (2)
22-25: Great improvement using t.TempDir()!Using
t.TempDir()instead of hardcoded paths improves test isolation and cleanup.
77-98:⚠️ Potential issueFix failing permission tests.
The test failures indicate that the permission-related assertions aren't working as expected. Here's how to fix them:
- assert.Error(t, PutContent("/proc/invalid/file.txt", "content")) + assert.Error(t, PutContent("/dev/null/file.txt", "content")) - assert.NoError(t, os.Mkdir(readOnlyDir, 0444)) + assert.NoError(t, os.Mkdir(readOnlyDir, 0400)) + assert.NoError(t, os.Chmod(readOnlyDir, 0400))The changes:
- Use
/dev/nullinstead of/procfor a more reliable permission error- Use
0400(read-only) permission and explicitly callChmodto ensure the directory is read-onlyLikely invalid or redundant comment.
🧰 Tools
🪛 GitHub Actions: Test
[error] 79-79: Test failure in TestPutContent: An error is expected but got nil.
[error] 83-83: Test failure in TestPutContent: An error is expected but got nil.
support/file/file.go (3)
14-34: Well-implemented functional options pattern!The implementation is clean, well-documented, and follows Go best practices.
42-47: Good refactoring to use GetContent!The change reduces code duplication and maintains proper error handling.
53-54: Good practice marking Create as deprecated!Clear migration path to PutContent is provided.
|
CI failed |
|
By the way we can rename GetContent and PutContent to Get and Put as we are doing in storage drivers. @hwbrzzl should we return a reader in Get method instead of string because reading a file in one go is not ideal (for a big size file)? |
I think if we’re dealing with large files, we can simply use os.OpenFile. The GetContent method is more of a convenience utility for reading small files, and its primary use case is scenarios like reading template stub files in artisan commands. |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
support/file/options.go (1)
5-11: Enhance documentation for Option type and struct.The documentation could be more descriptive about the available options and their default values.
-// Option represents an option for FilePutContents +// Option represents a configuration option for PutContent. type Option func(*option) type option struct { + // mode specifies the file permissions (default: os.ModePerm) mode os.FileMode + // append determines if content should be appended (default: false) append bool }support/file/file.go (3)
31-33: Enhance deprecation notice.The deprecation notice should provide more context about migration.
-// Create a file with the given content -// Deprecated: Use PutContent instead +// Create creates a file with the given content. +// Deprecated: Use PutContent instead, which provides more flexibility through options +// such as file permissions and append mode. func Create(file string, content string) error {
76-84: Add error documentation for GetContent.The function should document possible error conditions.
+// GetContent reads and returns the entire contents of the specified file as a string. +// It returns an error if the file doesn't exist or cannot be read. func GetContent(file string) (string, error) {
109-147: LGTM! Well-structured PutContent implementation.The implementation:
- Properly handles default options
- Creates directories if needed
- Uses appropriate file flags
- Has good error handling
However, consider adding comprehensive documentation:
+// PutContent creates or writes content to a file with configurable options. +// It creates the parent directories if they don't exist. +// +// Options: +// - WithMode: sets file permissions (default: os.ModePerm) +// - WithAppend: enables append mode (default: false) +// +// Returns an error if: +// - Directory creation fails +// - File cannot be opened +// - Write operation fails func PutContent(file string, content string, options ...Option) error {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
support/file/file.go(3 hunks)support/file/file_test.go(3 hunks)support/file/options.go(1 hunks)
🧰 Additional context used
📓 Learnings (1)
support/file/file.go (1)
Learnt from: almas1992
PR: goravel/framework#824
File: support/file/file.go:0-0
Timestamp: 2025-01-21T05:37:10.012Z
Learning: In Go, making a file read-only (chmod 0400) will cause os.OpenFile to fail with a permission error before reaching any write operations. This approach cannot be used to test write failures in functions that use os.OpenFile followed by write operations.
⏰ Context from checks skipped due to timeout of 300000ms (2)
- GitHub Check: test / windows (1.23)
- GitHub Check: test / windows (1.22)
🔇 Additional comments (5)
support/file/options.go (1)
13-25: LGTM! Well-implemented functional options pattern.The implementation follows Go best practices for functional options:
- Clear function names with With* prefix
- Proper use of closures
- Immutable option application
support/file/file.go (1)
19-26: LGTM! Good refactor to use GetContent.The Contain function now uses GetContent, improving code reuse.
support/file/file_test.go (3)
23-26: LGTM! Good use of t.TempDir().The test properly uses t.TempDir() for better test isolation.
66-76: LGTM! Good test coverage for GetContent.The test covers both success and failure cases.
78-105: LGTM! Comprehensive test coverage for PutContent.The test suite:
- Handles platform-specific paths
- Tests directory creation failure
- Tests read-only directory scenarios
- Verifies append and overwrite modes
- Checks file content and line counts
Note: Based on the retrieved learning, the read-only directory test is correctly skipped on Windows.
I’ve rebased the branch, but the CI is still failing. @hwbrzzl |
If it's |
|
@almas1992 Test External failure is acceptable for now, feel free to merge it. |
I’m unable to merge because some checks were not successful. |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (4)
support/file/file.go (3)
31-32: Enhance the deprecation notice.While marking the function as deprecated is good, the notice could be more informative by including:
- The version when it was deprecated
- A code example showing how to migrate to
PutContent-// Create a file with the given content -// Deprecated: Use PutContent instead +// Create a file with the given content. +// Deprecated: Use PutContent instead. For example: +// err := file.PutContent(filename, content) +// This function will be removed in a future version. func Create(file string, content string) error {
76-84: Add documentation for the GetContent function.While the implementation is correct, adding documentation would help users understand:
- The function's purpose
- Error conditions (e.g., file not found, permission issues)
- Memory considerations for large files
+// GetContent reads and returns the entire content of a file as a string. +// For large files, consider using os.OpenFile directly to avoid loading +// the entire content into memory. +// Returns an error if the file doesn't exist or cannot be read. func GetContent(file string) (string, error) {
109-147: Add comprehensive documentation for PutContent.The implementation is well-structured, but adding documentation would help users understand:
- The function's purpose and behavior
- Available options and their defaults
- Error conditions
+// PutContent writes the specified content to a file, creating it if it doesn't exist. +// The function supports the following options: +// - WithMode(mode os.FileMode): Set file permissions (default: os.ModePerm) +// - WithAppend(append bool): Append to file instead of overwriting (default: false) +// Returns an error if: +// - Directory creation fails +// - File cannot be opened +// - Write operation fails func PutContent(file string, content string, options ...Option) error {🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 143-144: support/file/file.go#L143-L144
Added lines #L143 - L144 were not covered by testssupport/file/file_test.go (1)
66-76: Consider adding more test cases.While the current test cases cover basic scenarios, consider adding:
- Empty file test case
- File with special characters
- Large file handling test
func TestGetContent(t *testing.T) { + // empty file + emptyFile := path.Join(t.TempDir(), "empty.txt") + assert.NoError(t, os.WriteFile(emptyFile, []byte{}, 0644)) + content, err := GetContent(emptyFile) + assert.Nil(t, err) + assert.Empty(t, content) + // file not exists
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
support/file/file.go(3 hunks)support/file/file_test.go(3 hunks)support/file/options.go(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- support/file/options.go
🧰 Additional context used
📓 Learnings (1)
support/file/file.go (1)
Learnt from: almas1992
PR: goravel/framework#824
File: support/file/file.go:0-0
Timestamp: 2025-01-21T05:37:10.012Z
Learning: In Go, making a file read-only (chmod 0400) will cause os.OpenFile to fail with a permission error before reaching any write operations. This approach cannot be used to test write failures in functions that use os.OpenFile followed by write operations.
🪛 GitHub Check: codecov/patch
support/file/file.go
[warning] 143-144: support/file/file.go#L143-L144
Added lines #L143 - L144 were not covered by tests
⏰ Context from checks skipped due to timeout of 300000ms (2)
- GitHub Check: test / windows (1.23)
- GitHub Check: test / windows (1.22)
🔇 Additional comments (4)
support/file/file.go (2)
20-25: LGTM! Good refactoring.The change improves code reusability by leveraging the new
GetContentfunction while maintaining proper error handling.
142-144: Add test coverage for write error handling.The static analysis indicates that the write error handling code is not covered by tests.
Note: Based on the retrieved learning from almas1992, making a file read-only won't help test write failures as it would cause
os.OpenFileto fail first. Consider using a mock filesystem for testing write failures.🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 143-144: support/file/file.go#L143-L144
Added lines #L143 - L144 were not covered by testssupport/file/file_test.go (2)
23-26: LGTM! Good test improvement.Using
t.TempDir()improves test isolation and reliability.
78-101: LGTM! Comprehensive test coverage.The test cases effectively cover:
- Directory creation failure
- File operations (create, append, overwrite)
- File permissions
- Platform-specific handling

📑 Description
This PR introduces two new methods,
GetContentandPutContent, to the support/file package in Goravel.GetContent: Retrieves the contents of a file as a string.
PutContent: Writes a string to a file, creating or replacing it as needed.
Closes https://github.com/goravel/goravel/issues/?
Summary by CodeRabbit
Release Notes
New Features
GetContent) and writing (PutContent) file content.Improvements
GetContentandPutContent.Deprecation
Createfunction as deprecated.These updates provide developers with more granular control over file operations, making file management more intuitive and flexible.
✅ Checks