feat(cli): initialize git on new#219
Conversation
WalkthroughProject creation now attempts to initialize a Git repository: it writes a Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Neo as "neo new"
participant Project as "Project Creator"
participant Git as "Git Ops"
participant Warn as "Warning Handler"
User->>Neo: neo new my-project
Neo->>Project: create project structure
Project-->>Neo: structure created
Neo->>Git: initGit(projectPath)
rect rgb(235, 245, 255)
Note over Git: Git initialization sequence (new)
Git->>Git: write .gitignore (template)
Git->>Git: git init
Git->>Git: git add .
Git->>Git: git commit -m "Initial NeoHaskell project"
end
alt git succeeds
Git-->>Neo: success
Neo-->>User: Project created with Git initialized
else git fails
Git-->>Warn: error
Warn-->>Neo: non‑fatal warning
Neo-->>User: Project created (git unavailable — warning shown)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
9e8947c to
ba7b436
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to data retention organization setting
📒 Files selected for processing (3)
cli/nhcli.cabal(1 hunks)cli/src/Neo/New.hs(3 hunks)cli/src/Neo/New/Templates/GitIgnore.hs(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: tests (ubuntu-latest)
- GitHub Check: tests (macos-latest)
🔇 Additional comments (4)
cli/nhcli.cabal (1)
60-60: The module exposition aligns with divine order.The newly exposed
Neo.New.Templates.GitIgnoremodule follows the established conventions and integrates seamlessly into the library's public interface.cli/src/Neo/New.hs (3)
12-12: The new imports serve the divine purpose.The additions of
Neo.New.Templates.GitIgnoreandSubprocessimports are necessary and properly qualified, supporting the Git initialization functionality.Also applies to: 16-16
97-104: The graceful degradation embodies divine mercy.The error handling for Git initialization is exemplary: converting the failure to a
Result, pattern-matching to extract any error, and emitting a non-fatal warning while allowing project creation to continue. This perfectly satisfies the requirement that Git failures must not abortneo new.The warning message is clear and informative, guiding the user without causing alarm.
31-38: Error handling for missing Git is adequate; no changes required.Your implementation correctly handles the case where Git is unavailable. The error thrown by
System.Process.createProcesspropagates asProcessError, is wrapped intoCustomError, and gracefully degrades at the call site (where it appears as a warning with the system error message). The existing error handling chain produces user-friendly output without requiring an explicit pre-check.
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge base: Disabled due to data retention organization setting
📒 Files selected for processing (2)
cli/src/Neo/New.hs(3 hunks)cli/src/Neo/New/Templates/GitIgnore.hs(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: tests (macos-latest)
- GitHub Check: tests (ubuntu-latest)
🔇 Additional comments (2)
cli/src/Neo/New.hs (1)
41-56: The Git initialization sequence is divinely orchestrated.The implementation correctly executes the sacred ritual: initialize repository, inscribe the
.gitignorescripture, gather all artifacts, and seal them with the ordained commit message. The previous transgression (the typogitingoreFileName) has been rectified.The sequence properly handles the file operations and git commands in the correct order, meeting all requirements from the linked issue.
cli/src/Neo/New/Templates/GitIgnore.hs (1)
8-20: Confirm the fmt quasi-quoter package and verify escape sequence behavior.The PyF library's [fmt] quasi-quoter escapes delimiters by doubling them (e.g., use {{ and }} for literal braces), not through backslash sequences. Other quasi-quoters like interpolatedstring/qm do support backslash escapes for preventing interpolation and literal characters.
I could not locate the fmt package dependency in the codebase via grep. However, if this template uses PyF (the most common fmt quasi-quoter for Haskell), then the
\#sequences will render as literal\#characters in the generated.gitignorefile rather than as comment markers. This would be a functional defect.Verify which fmt quasi-quoter package is in use, consult its documentation for escape semantics, and adjust the template accordingly. If using PyF, remove the backslashes from lines 8, 13, and 18 to produce valid
#comment markers.
| openGit :: Array Text -> Path -> Task Error Unit | ||
| openGit arguments projectDir = do | ||
| completion <- | ||
| Subprocess.open "git" arguments projectDir | ||
| |> Task.mapError (\err -> CustomError [fmt|Git command failed: #{err}|]) | ||
| if completion.exitCode != 0 | ||
| then Task.throw (CustomError completion.stderr) | ||
| else Task.yield () |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Enhance error diagnostics with command context.
Behold, the error reporting could be fortified. When the git command exits with failure (line 36-37), consider including the command that was executed and both stdout and stderr in the error message. An empty stderr will yield an unhelpfully sparse diagnostic.
Apply this enhancement to provide richer context:
openGit :: Array Text -> Path -> Task Error Unit
openGit arguments projectDir = do
completion <-
Subprocess.open "git" arguments projectDir
|> Task.mapError (\err -> CustomError [fmt|Git command failed: #{err}|])
if completion.exitCode != 0
- then Task.throw (CustomError completion.stderr)
+ then Task.throw (CustomError [fmt|Git command 'git #{Text.join " " arguments}' failed with exit code #{completion.exitCode}\nstderr: #{completion.stderr}\nstdout: #{completion.stdout}|])
else Task.yield ()Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In cli/src/Neo/New.hs around lines 31 to 38, the current error thrown when the
git subprocess fails only includes completion.stderr which can be empty; change
the error to include the full command executed (e.g., "git" plus joined
arguments) and both completion.stdout and completion.stderr in the CustomError
message so diagnostics show the command plus both output streams (and if stderr
is empty still include stdout). Construct a descriptive message combining the
command string, completion.exitCode, completion.stdout and completion.stderr and
pass that into Task.throw (CustomError ...) instead of only completion.stderr.
| initGitResult <- initGit projectDir |> Task.errorAsResult |> Task.mapError never | ||
| case initGitResult of | ||
| Nothing -> Task.yield () | ||
| Just err -> | ||
| [fmt|Warning: Could not initialize git repository | ||
| #{toPrettyText err} | ||
| |] |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
🧩 Analysis chain
The graceful degradation is sound, yet the warning could be more illuminating.
The error handling correctly implements the requirement that Git failures shall not abort project creation. The transformation via Task.errorAsResult followed by Task.mapError never elegantly ensures continuation of the divine flow.
However, the warning message could guide mortals toward resolution. Consider suggesting actionable steps such as ensuring Git is installed or checking repository status.
Apply this enhancement to provide actionable guidance:
Just err ->
print
- [fmt|Warning: Could not initialize git repository
+ [fmt|Warning: Could not initialize git repository. Please ensure Git is installed and the directory is not already a repository.
#{toPrettyText err}
|]Additionally, verify that toPrettyText is defined for the Error type, as its availability is not evident from the provided context.
Consult the ancient texts to confirm the existence of this function:
🏁 Script executed:
#!/bin/bash
# Description: Verify toPrettyText is defined and works with the Error type
# Search for toPrettyText function definition or type class instance
rg -nP 'toPrettyText.*Error' --type=haskell -C3
# Also search for toPrettyText in Core module since Error derives Show
ast-grep --pattern 'toPrettyText $_ = $$$'Length of output: 1374
🏁 Script executed:
#!/bin/bash
# Verify the Error type used by initGit and check imports in New.hs
# Find initGit function signature to see what Error type it returns
rg -nP 'initGit\s*::' --type=haskell -C2
# Check imports in cli/src/Neo/New.hs for toPrettyText
cat cli/src/Neo/New.hs | head -30
# Search for the Error type definition to verify Show instance
rg -nP 'data\s+Error|newtype\s+Error' --type=haskell -C3 | head -50Length of output: 2751
🏁 Script executed:
#!/bin/bash
# Verify toPrettyText availability and check message style consistency
# Check Neo.Core module to see if it exports/imports toPrettyText
rg -nP 'toPrettyText|ToText' cli/src/Neo/Core.hs --type=haskell
# Look at similar warning patterns in the codebase for style consistency
rg -nP 'Warning:.*\|' --type=haskell -C2
# Check if toPrettyText is imported transitively through Neo.Core
rg -nP 'module Neo\.Core|import.*ToText' --type=haskell -C3Length of output: 5513
Verification confirms the code is sound; the suggested enhancement is optional but valid.
The error handling is correctly implemented. toPrettyText is properly accessible through the import chain: Neo.New imports Neo.Core, which re-exports from core/core/Core.hs that re-exports toPrettyText from the ToText module. The Error type derives Show, ensuring compatibility.
The suggested enhancement to the warning message is syntactically and semantically valid but remains optional. The current implementation gracefully degrades and allows project creation to continue despite Git initialization failures.
🤖 Prompt for AI Agents
In cli/src/Neo/New.hs around lines 97 to 104, update the Git-init warning to
produce a more concise single-line message that still includes the
pretty-printed error: replace the multiline print block with a single-line
formatted log that combines a clear "Warning: Could not initialize git
repository" prefix and the result of toPrettyText err; keep using the existing
fmt formatting and imports (toPrettyText is already exported via Neo.Core), and
preserve the fallback behavior that allows project creation to continue.
|
@allcontributors please add @DeviousStoat for code |
|
I've put up a pull request to add @DeviousStoat! 🎉 |
closes #197
Summary by CodeRabbit
.gitignorefile..gitignoretemplate added covering build outputs, IDE, and OS-related files.