mirror of
https://github.com/yarlson/lnk.git
synced 2025-09-02 18:12:33 +02:00
feat(output): implement configurable color and emoji output
Add new output formatting system with flags for color and emoji control: - Introduce OutputConfig and Writer structs for flexible output handling - Add --colors and --emoji/--no-emoji global flags - Refactor commands to use new Writer for consistent formatting - Separate error content from presentation for better flexibility
This commit is contained in:
84
internal/core/errors.go
Normal file
84
internal/core/errors.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package core
|
||||
|
||||
import "fmt"
|
||||
|
||||
// LnkError represents a structured error with separate content and formatting hints
|
||||
type LnkError struct {
|
||||
Message string
|
||||
Suggestion string
|
||||
Path string
|
||||
ErrorType string
|
||||
}
|
||||
|
||||
func (e *LnkError) Error() string {
|
||||
if e.Suggestion != "" {
|
||||
return fmt.Sprintf("%s\n %s", e.Message, e.Suggestion)
|
||||
}
|
||||
return e.Message
|
||||
}
|
||||
|
||||
// Error constructors that separate content from presentation
|
||||
|
||||
func ErrDirectoryContainsManagedFiles(path string) error {
|
||||
return &LnkError{
|
||||
Message: fmt.Sprintf("Directory %s already contains managed files", path),
|
||||
Suggestion: "Use 'lnk pull' to update from remote instead of 'lnk init -r'",
|
||||
Path: path,
|
||||
ErrorType: "managed_files_exist",
|
||||
}
|
||||
}
|
||||
|
||||
func ErrDirectoryContainsGitRepo(path string) error {
|
||||
return &LnkError{
|
||||
Message: fmt.Sprintf("Directory %s contains an existing Git repository", path),
|
||||
Suggestion: "Please backup or move the existing repository before initializing lnk",
|
||||
Path: path,
|
||||
ErrorType: "git_repo_exists",
|
||||
}
|
||||
}
|
||||
|
||||
func ErrFileAlreadyManaged(path string) error {
|
||||
return &LnkError{
|
||||
Message: fmt.Sprintf("File is already managed by lnk: %s", path),
|
||||
Path: path,
|
||||
ErrorType: "already_managed",
|
||||
}
|
||||
}
|
||||
|
||||
func ErrFileNotManaged(path string) error {
|
||||
return &LnkError{
|
||||
Message: fmt.Sprintf("File is not managed by lnk: %s", path),
|
||||
Path: path,
|
||||
ErrorType: "not_managed",
|
||||
}
|
||||
}
|
||||
|
||||
func ErrRepositoryNotInitialized() error {
|
||||
return &LnkError{
|
||||
Message: "Lnk repository not initialized",
|
||||
Suggestion: "Run 'lnk init' first",
|
||||
ErrorType: "not_initialized",
|
||||
}
|
||||
}
|
||||
|
||||
func ErrBootstrapScriptNotFound(script string) error {
|
||||
return &LnkError{
|
||||
Message: fmt.Sprintf("Bootstrap script not found: %s", script),
|
||||
Path: script,
|
||||
ErrorType: "script_not_found",
|
||||
}
|
||||
}
|
||||
|
||||
func ErrBootstrapScriptFailed(err error) error {
|
||||
return &LnkError{
|
||||
Message: fmt.Sprintf("Bootstrap script failed with error: %v", err),
|
||||
ErrorType: "script_failed",
|
||||
}
|
||||
}
|
||||
|
||||
func ErrBootstrapScriptNotExecutable(err error) error {
|
||||
return &LnkError{
|
||||
Message: fmt.Sprintf("Failed to make bootstrap script executable: %v", err),
|
||||
ErrorType: "script_permissions",
|
||||
}
|
||||
}
|
@@ -156,7 +156,7 @@ func (l *Lnk) InitWithRemoteForce(remoteURL string, force bool) error {
|
||||
// Safety check: prevent data loss by checking for existing managed files
|
||||
if l.HasUserContent() {
|
||||
if !force {
|
||||
return fmt.Errorf("❌ Directory \033[31m%s\033[0m already contains managed files\n 💡 Use 'lnk pull' to update from remote instead of 'lnk init -r'", l.repoPath)
|
||||
return ErrDirectoryContainsManagedFiles(l.repoPath)
|
||||
}
|
||||
}
|
||||
// Clone from remote
|
||||
@@ -176,7 +176,7 @@ func (l *Lnk) InitWithRemoteForce(remoteURL string, force bool) error {
|
||||
return nil
|
||||
} else {
|
||||
// It's not a lnk repository, error to prevent data loss
|
||||
return fmt.Errorf("❌ Directory \033[31m%s\033[0m contains an existing Git repository\n 💡 Please backup or move the existing repository before initializing lnk", l.repoPath)
|
||||
return ErrDirectoryContainsGitRepo(l.repoPath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ func (l *Lnk) Add(filePath string) error {
|
||||
}
|
||||
for _, item := range managedItems {
|
||||
if item == relativePath {
|
||||
return fmt.Errorf("❌ File is already managed by lnk: \033[31m%s\033[0m", relativePath)
|
||||
return ErrFileAlreadyManaged(relativePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ func (l *Lnk) AddMultiple(paths []string) error {
|
||||
}
|
||||
for _, item := range managedItems {
|
||||
if item == relativePath {
|
||||
return fmt.Errorf("❌ File is already managed by lnk: \033[31m%s\033[0m", relativePath)
|
||||
return ErrFileAlreadyManaged(relativePath)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,7 +476,7 @@ func (l *Lnk) Remove(filePath string) error {
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return fmt.Errorf("❌ File is not managed by lnk: \033[31m%s\033[0m", relativePath)
|
||||
return ErrFileNotManaged(relativePath)
|
||||
}
|
||||
|
||||
// Get the target path in the repository
|
||||
@@ -551,7 +551,7 @@ type StatusInfo struct {
|
||||
func (l *Lnk) Status() (*StatusInfo, error) {
|
||||
// Check if repository is initialized
|
||||
if !l.git.IsGitRepository() {
|
||||
return nil, fmt.Errorf("❌ Lnk repository not initialized\n 💡 Run \033[1mlnk init\033[0m first")
|
||||
return nil, ErrRepositoryNotInitialized()
|
||||
}
|
||||
|
||||
gitStatus, err := l.git.GetStatus()
|
||||
@@ -571,7 +571,7 @@ func (l *Lnk) Status() (*StatusInfo, error) {
|
||||
func (l *Lnk) Push(message string) error {
|
||||
// Check if repository is initialized
|
||||
if !l.git.IsGitRepository() {
|
||||
return fmt.Errorf("❌ Lnk repository not initialized\n 💡 Run \033[1mlnk init\033[0m first")
|
||||
return ErrRepositoryNotInitialized()
|
||||
}
|
||||
|
||||
// Check if there are any changes
|
||||
@@ -601,7 +601,7 @@ func (l *Lnk) Push(message string) error {
|
||||
func (l *Lnk) Pull() ([]string, error) {
|
||||
// Check if repository is initialized
|
||||
if !l.git.IsGitRepository() {
|
||||
return nil, fmt.Errorf("❌ Lnk repository not initialized\n 💡 Run \033[1mlnk init\033[0m first")
|
||||
return nil, ErrRepositoryNotInitialized()
|
||||
}
|
||||
|
||||
// Pull changes from remote (this will be a no-op in tests since we don't have real remotes)
|
||||
@@ -622,7 +622,7 @@ func (l *Lnk) Pull() ([]string, error) {
|
||||
func (l *Lnk) List() ([]string, error) {
|
||||
// Check if repository is initialized
|
||||
if !l.git.IsGitRepository() {
|
||||
return nil, fmt.Errorf("❌ Lnk repository not initialized\n 💡 Run \033[1mlnk init\033[0m first")
|
||||
return nil, ErrRepositoryNotInitialized()
|
||||
}
|
||||
|
||||
// Get managed items from .lnk file
|
||||
@@ -822,7 +822,7 @@ func (l *Lnk) writeManagedItems(items []string) error {
|
||||
func (l *Lnk) FindBootstrapScript() (string, error) {
|
||||
// Check if repository is initialized
|
||||
if !l.git.IsGitRepository() {
|
||||
return "", fmt.Errorf("❌ Lnk repository not initialized\n 💡 Run \033[1mlnk init\033[0m first")
|
||||
return "", ErrRepositoryNotInitialized()
|
||||
}
|
||||
|
||||
// Look for bootstrap.sh - simple, opinionated choice
|
||||
@@ -840,12 +840,12 @@ func (l *Lnk) RunBootstrapScript(scriptName string) error {
|
||||
|
||||
// Verify the script exists
|
||||
if _, err := os.Stat(scriptPath); os.IsNotExist(err) {
|
||||
return fmt.Errorf("❌ Bootstrap script not found: \033[31m%s\033[0m", scriptName)
|
||||
return ErrBootstrapScriptNotFound(scriptName)
|
||||
}
|
||||
|
||||
// Make sure it's executable
|
||||
if err := os.Chmod(scriptPath, 0755); err != nil {
|
||||
return fmt.Errorf("❌ Failed to make bootstrap script executable: %w", err)
|
||||
return ErrBootstrapScriptNotExecutable(err)
|
||||
}
|
||||
|
||||
// Run with bash (since we only support bootstrap.sh)
|
||||
@@ -861,7 +861,7 @@ func (l *Lnk) RunBootstrapScript(scriptName string) error {
|
||||
|
||||
// Run the script
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("❌ Bootstrap script failed with error: %w", err)
|
||||
return ErrBootstrapScriptFailed(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -988,7 +988,7 @@ func (l *Lnk) addMultipleWithProgress(paths []string, progress ProgressCallback)
|
||||
}
|
||||
for _, item := range managedItems {
|
||||
if item == relativePath {
|
||||
return fmt.Errorf("❌ File is already managed by lnk: \033[31m%s\033[0m", relativePath)
|
||||
return ErrFileAlreadyManaged(relativePath)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,28 +1,7 @@
|
||||
package fs
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ANSI color codes for consistent formatting
|
||||
const (
|
||||
colorReset = "\033[0m"
|
||||
colorRed = "\033[31m"
|
||||
colorBold = "\033[1m"
|
||||
)
|
||||
|
||||
// formatError creates a consistently formatted error message with ❌ prefix
|
||||
func formatError(message string, args ...interface{}) string {
|
||||
return fmt.Sprintf("❌ "+message, args...)
|
||||
}
|
||||
|
||||
// formatPath formats a file path with red color
|
||||
func formatPath(path string) string {
|
||||
return fmt.Sprintf("%s%s%s", colorRed, path, colorReset)
|
||||
}
|
||||
|
||||
// formatCommand formats a command with bold styling
|
||||
func formatCommand(command string) string {
|
||||
return fmt.Sprintf("%s%s%s", colorBold, command, colorReset)
|
||||
}
|
||||
// Structured errors that separate content from presentation
|
||||
// These will be formatted by the cmd package based on user preferences
|
||||
|
||||
// FileNotExistsError represents an error when a file does not exist
|
||||
type FileNotExistsError struct {
|
||||
@@ -31,20 +10,25 @@ type FileNotExistsError struct {
|
||||
}
|
||||
|
||||
func (e *FileNotExistsError) Error() string {
|
||||
return formatError("File or directory not found: %s", formatPath(e.Path))
|
||||
return "File or directory not found: " + e.Path
|
||||
}
|
||||
|
||||
func (e *FileNotExistsError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// GetPath returns the path for formatting purposes
|
||||
func (e *FileNotExistsError) GetPath() string {
|
||||
return e.Path
|
||||
}
|
||||
|
||||
// FileCheckError represents an error when failing to check a file
|
||||
type FileCheckError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *FileCheckError) Error() string {
|
||||
return formatError("Unable to access file. Please check file permissions and try again.")
|
||||
return "Unable to access file. Please check file permissions and try again."
|
||||
}
|
||||
|
||||
func (e *FileCheckError) Unwrap() error {
|
||||
@@ -57,7 +41,15 @@ type UnsupportedFileTypeError struct {
|
||||
}
|
||||
|
||||
func (e *UnsupportedFileTypeError) Error() string {
|
||||
return formatError("Cannot manage this type of file: %s\n 💡 lnk can only manage regular files and directories", formatPath(e.Path))
|
||||
return "Cannot manage this type of file: " + e.Path
|
||||
}
|
||||
|
||||
func (e *UnsupportedFileTypeError) GetPath() string {
|
||||
return e.Path
|
||||
}
|
||||
|
||||
func (e *UnsupportedFileTypeError) GetSuggestion() string {
|
||||
return "lnk can only manage regular files and directories"
|
||||
}
|
||||
|
||||
func (e *UnsupportedFileTypeError) Unwrap() error {
|
||||
@@ -70,8 +62,15 @@ type NotManagedByLnkError struct {
|
||||
}
|
||||
|
||||
func (e *NotManagedByLnkError) Error() string {
|
||||
return formatError("File is not managed by lnk: %s\n 💡 Use %s to manage this file first",
|
||||
formatPath(e.Path), formatCommand("lnk add"))
|
||||
return "File is not managed by lnk: " + e.Path
|
||||
}
|
||||
|
||||
func (e *NotManagedByLnkError) GetPath() string {
|
||||
return e.Path
|
||||
}
|
||||
|
||||
func (e *NotManagedByLnkError) GetSuggestion() string {
|
||||
return "Use 'lnk add' to manage this file first"
|
||||
}
|
||||
|
||||
func (e *NotManagedByLnkError) Unwrap() error {
|
||||
@@ -84,7 +83,7 @@ type SymlinkReadError struct {
|
||||
}
|
||||
|
||||
func (e *SymlinkReadError) Error() string {
|
||||
return formatError("Unable to read symlink. The file may be corrupted or have invalid permissions.")
|
||||
return "Unable to read symlink. The file may be corrupted or have invalid permissions."
|
||||
}
|
||||
|
||||
func (e *SymlinkReadError) Unwrap() error {
|
||||
@@ -98,7 +97,7 @@ type DirectoryCreationError struct {
|
||||
}
|
||||
|
||||
func (e *DirectoryCreationError) Error() string {
|
||||
return formatError("Failed to create directory. Please check permissions and available disk space.")
|
||||
return "Failed to create directory. Please check permissions and available disk space."
|
||||
}
|
||||
|
||||
func (e *DirectoryCreationError) Unwrap() error {
|
||||
@@ -111,9 +110,21 @@ type RelativePathCalculationError struct {
|
||||
}
|
||||
|
||||
func (e *RelativePathCalculationError) Error() string {
|
||||
return formatError("Unable to create symlink due to path configuration issues. Please check file locations.")
|
||||
return "Unable to create symlink due to path configuration issues. Please check file locations."
|
||||
}
|
||||
|
||||
func (e *RelativePathCalculationError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// ErrorWithPath is an interface for errors that have an associated file path
|
||||
type ErrorWithPath interface {
|
||||
error
|
||||
GetPath() string
|
||||
}
|
||||
|
||||
// ErrorWithSuggestion is an interface for errors that provide helpful suggestions
|
||||
type ErrorWithSuggestion interface {
|
||||
error
|
||||
GetSuggestion() string
|
||||
}
|
||||
|
@@ -1,29 +1,7 @@
|
||||
package git
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ANSI color codes for consistent formatting
|
||||
const (
|
||||
colorReset = "\033[0m"
|
||||
colorBold = "\033[1m"
|
||||
colorGreen = "\033[32m"
|
||||
colorYellow = "\033[33m"
|
||||
)
|
||||
|
||||
// formatError creates a consistently formatted error message with ❌ prefix
|
||||
func formatError(message string, args ...interface{}) string {
|
||||
return fmt.Sprintf("❌ "+message, args...)
|
||||
}
|
||||
|
||||
// formatURL formats a URL with styling
|
||||
func formatURL(url string) string {
|
||||
return fmt.Sprintf("%s%s%s", colorBold, url, colorReset)
|
||||
}
|
||||
|
||||
// formatRemote formats a remote name with styling
|
||||
func formatRemote(remote string) string {
|
||||
return fmt.Sprintf("%s%s%s", colorGreen, remote, colorReset)
|
||||
}
|
||||
// Structured errors that separate content from presentation
|
||||
// These will be formatted by the cmd package based on user preferences
|
||||
|
||||
// GitInitError represents an error during git initialization
|
||||
type GitInitError struct {
|
||||
@@ -32,7 +10,7 @@ type GitInitError struct {
|
||||
}
|
||||
|
||||
func (e *GitInitError) Error() string {
|
||||
return formatError("Failed to initialize git repository. Please ensure git is installed and try again.")
|
||||
return "Failed to initialize git repository. Please ensure git is installed and try again."
|
||||
}
|
||||
|
||||
func (e *GitInitError) Unwrap() error {
|
||||
@@ -45,7 +23,7 @@ type BranchSetupError struct {
|
||||
}
|
||||
|
||||
func (e *BranchSetupError) Error() string {
|
||||
return formatError("Failed to set up the default branch. Please check your git installation.")
|
||||
return "Failed to set up the default branch. Please check your git installation."
|
||||
}
|
||||
|
||||
func (e *BranchSetupError) Unwrap() error {
|
||||
@@ -60,8 +38,19 @@ type RemoteExistsError struct {
|
||||
}
|
||||
|
||||
func (e *RemoteExistsError) Error() string {
|
||||
return formatError("Remote %s is already configured with a different repository (%s). Cannot add %s.",
|
||||
formatRemote(e.Remote), formatURL(e.ExistingURL), formatURL(e.NewURL))
|
||||
return "Remote " + e.Remote + " is already configured with a different repository (" + e.ExistingURL + "). Cannot add " + e.NewURL + "."
|
||||
}
|
||||
|
||||
func (e *RemoteExistsError) GetRemote() string {
|
||||
return e.Remote
|
||||
}
|
||||
|
||||
func (e *RemoteExistsError) GetExistingURL() string {
|
||||
return e.ExistingURL
|
||||
}
|
||||
|
||||
func (e *RemoteExistsError) GetNewURL() string {
|
||||
return e.NewURL
|
||||
}
|
||||
|
||||
func (e *RemoteExistsError) Unwrap() error {
|
||||
@@ -79,24 +68,28 @@ func (e *GitCommandError) Error() string {
|
||||
// Provide user-friendly messages based on common command types
|
||||
switch e.Command {
|
||||
case "add":
|
||||
return formatError("Failed to stage files for commit. Please check file permissions and try again.")
|
||||
return "Failed to stage files for commit. Please check file permissions and try again."
|
||||
case "commit":
|
||||
return formatError("Failed to create commit. Please ensure you have staged changes and try again.")
|
||||
return "Failed to create commit. Please ensure you have staged changes and try again."
|
||||
case "remote add":
|
||||
return formatError("Failed to add remote repository. Please check the repository URL and try again.")
|
||||
return "Failed to add remote repository. Please check the repository URL and try again."
|
||||
case "rm":
|
||||
return formatError("Failed to remove file from git tracking. Please check if the file exists and try again.")
|
||||
return "Failed to remove file from git tracking. Please check if the file exists and try again."
|
||||
case "log":
|
||||
return formatError("Failed to retrieve commit history.")
|
||||
return "Failed to retrieve commit history."
|
||||
case "remote":
|
||||
return formatError("Failed to retrieve remote repository information.")
|
||||
return "Failed to retrieve remote repository information."
|
||||
case "clone":
|
||||
return formatError("Failed to clone repository. Please check the repository URL and your network connection.")
|
||||
return "Failed to clone repository. Please check the repository URL and your network connection."
|
||||
default:
|
||||
return formatError("Git operation failed. Please check your repository state and try again.")
|
||||
return "Git operation failed. Please check your repository state and try again."
|
||||
}
|
||||
}
|
||||
|
||||
func (e *GitCommandError) GetCommand() string {
|
||||
return e.Command
|
||||
}
|
||||
|
||||
func (e *GitCommandError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
@@ -105,7 +98,7 @@ func (e *GitCommandError) Unwrap() error {
|
||||
type NoRemoteError struct{}
|
||||
|
||||
func (e *NoRemoteError) Error() string {
|
||||
return formatError("No remote repository is configured. Please add a remote repository first.")
|
||||
return "No remote repository is configured. Please add a remote repository first."
|
||||
}
|
||||
|
||||
func (e *NoRemoteError) Unwrap() error {
|
||||
@@ -119,7 +112,11 @@ type RemoteNotFoundError struct {
|
||||
}
|
||||
|
||||
func (e *RemoteNotFoundError) Error() string {
|
||||
return formatError("Remote repository %s is not configured.", formatRemote(e.Remote))
|
||||
return "Remote repository " + e.Remote + " is not configured."
|
||||
}
|
||||
|
||||
func (e *RemoteNotFoundError) GetRemote() string {
|
||||
return e.Remote
|
||||
}
|
||||
|
||||
func (e *RemoteNotFoundError) Unwrap() error {
|
||||
@@ -133,7 +130,7 @@ type GitConfigError struct {
|
||||
}
|
||||
|
||||
func (e *GitConfigError) Error() string {
|
||||
return formatError("Failed to configure git settings. Please check your git installation.")
|
||||
return "Failed to configure git settings. Please check your git installation."
|
||||
}
|
||||
|
||||
func (e *GitConfigError) Unwrap() error {
|
||||
@@ -146,7 +143,7 @@ type UncommittedChangesError struct {
|
||||
}
|
||||
|
||||
func (e *UncommittedChangesError) Error() string {
|
||||
return formatError("Failed to check repository status. Please verify your git repository is valid.")
|
||||
return "Failed to check repository status. Please verify your git repository is valid."
|
||||
}
|
||||
|
||||
func (e *UncommittedChangesError) Unwrap() error {
|
||||
@@ -160,7 +157,11 @@ type DirectoryRemovalError struct {
|
||||
}
|
||||
|
||||
func (e *DirectoryRemovalError) Error() string {
|
||||
return formatError("Failed to prepare directory for operation. Please check directory permissions.")
|
||||
return "Failed to prepare directory for operation. Please check directory permissions."
|
||||
}
|
||||
|
||||
func (e *DirectoryRemovalError) GetPath() string {
|
||||
return e.Path
|
||||
}
|
||||
|
||||
func (e *DirectoryRemovalError) Unwrap() error {
|
||||
@@ -174,7 +175,11 @@ type DirectoryCreationError struct {
|
||||
}
|
||||
|
||||
func (e *DirectoryCreationError) Error() string {
|
||||
return formatError("Failed to create directory. Please check permissions and available disk space.")
|
||||
return "Failed to create directory. Please check permissions and available disk space."
|
||||
}
|
||||
|
||||
func (e *DirectoryCreationError) GetPath() string {
|
||||
return e.Path
|
||||
}
|
||||
|
||||
func (e *DirectoryCreationError) Unwrap() error {
|
||||
@@ -190,9 +195,13 @@ type PushError struct {
|
||||
|
||||
func (e *PushError) Error() string {
|
||||
if e.Reason != "" {
|
||||
return formatError("Cannot push changes: %s", e.Reason)
|
||||
return "Cannot push changes: " + e.Reason
|
||||
}
|
||||
return formatError("Failed to push changes to remote repository. Please check your network connection and repository permissions.")
|
||||
return "Failed to push changes to remote repository. Please check your network connection and repository permissions."
|
||||
}
|
||||
|
||||
func (e *PushError) GetReason() string {
|
||||
return e.Reason
|
||||
}
|
||||
|
||||
func (e *PushError) Unwrap() error {
|
||||
@@ -208,11 +217,33 @@ type PullError struct {
|
||||
|
||||
func (e *PullError) Error() string {
|
||||
if e.Reason != "" {
|
||||
return formatError("Cannot pull changes: %s", e.Reason)
|
||||
return "Cannot pull changes: " + e.Reason
|
||||
}
|
||||
return formatError("Failed to pull changes from remote repository. Please check your network connection and resolve any conflicts.")
|
||||
return "Failed to pull changes from remote repository. Please check your network connection and resolve any conflicts."
|
||||
}
|
||||
|
||||
func (e *PullError) GetReason() string {
|
||||
return e.Reason
|
||||
}
|
||||
|
||||
func (e *PullError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
// ErrorWithPath is an interface for git errors that have an associated file path
|
||||
type ErrorWithPath interface {
|
||||
error
|
||||
GetPath() string
|
||||
}
|
||||
|
||||
// ErrorWithRemote is an interface for git errors that involve a remote
|
||||
type ErrorWithRemote interface {
|
||||
error
|
||||
GetRemote() string
|
||||
}
|
||||
|
||||
// ErrorWithReason is an interface for git errors that have a specific reason
|
||||
type ErrorWithReason interface {
|
||||
error
|
||||
GetReason() string
|
||||
}
|
||||
|
Reference in New Issue
Block a user