README.md in git-2.0.0.pre1 vs README.md in git-2.0.0.pre2
- old
+ new
@@ -9,10 +9,22 @@
[![Documentation](https://img.shields.io/badge/Documentation-Latest-green)](https://rubydoc.info/gems/git/)
[![Change Log](https://img.shields.io/badge/CHANGELOG-Latest-green)](https://rubydoc.info/gems/git/file/CHANGELOG.md)
[![Build Status](https://github.com/ruby-git/ruby-git/workflows/CI/badge.svg?branch=master)](https://github.com/ruby-git/ruby-git/actions?query=workflow%3ACI)
[![Code Climate](https://codeclimate.com/github/ruby-git/ruby-git.png)](https://codeclimate.com/github/ruby-git/ruby-git)
+* [Summary](#summary)
+* [v2.0.0 pre-release](#v200-pre-release)
+* [Install](#install)
+* [Major Objects](#major-objects)
+* [Errors Raised By This Gem](#errors-raised-by-this-gem)
+* [Specifying And Handling Timeouts](#specifying-and-handling-timeouts)
+* [Examples](#examples)
+* [Ruby version support policy](#ruby-version-support-policy)
+* [License](#license)
+
+## Summary
+
The [git gem](https://rubygems.org/gems/git) provides an API that can be used to
create, read, and manipulate Git repositories by wrapping system calls to the `git`
command line. The API can be used for working with Git in complex interactions
including branching and merging, object inspection and manipulation, history, patch
generation and more.
@@ -88,15 +100,123 @@
`@git.log.all.each { |commit| [block] }`
**Git::Worktrees** - Enumerable object that holds `Git::Worktree objects`.
+## Errors Raised By This Gem
+
+This gem raises custom errors that derive from `Git::Error`. These errors are
+arranged in the following class heirarchy:
+
+Error heirarchy:
+
+```text
+Error
+└── CommandLineError
+ ├── FailedError
+ └── SignaledError
+ └── TimeoutError
+```
+
+Other standard errors may also be raised like `ArgumentError`. Each method should
+document the errors it may raise.
+
+Description of each Error class:
+
+* `Error`: This catch-all error serves as the base class for other custom errors in this
+ gem. Errors of this class are raised when no more approriate specific error to
+ raise.
+* `CommandLineError`: This error is raised when there's a problem executing the git
+ command line. This gem will raise a more specific error depending on how the
+ command line failed.
+* `FailedError`: This error is raised when the git command line exits with a non-zero
+ status code that is not expected by the git gem.
+* `SignaledError`: This error is raised when the git command line is terminated as a
+ result of receiving a signal. This could happen if the process is forcibly
+ terminated or if there is a serious system error.
+* `TimeoutError`: This is a specific type of `SignaledError` that is raised when the
+ git command line operation times out and is killed via the SIGKILL signal. This
+ happens if the operation takes longer than the timeout duration configured in
+ `Git.config.timeout` or via the `:timeout` parameter given in git methods that
+ support this parameter.
+
+`Git::GitExecuteError` remains as an alias for `Git::Error`. It is considered
+deprecated as of git-2.0.0.
+
+Here is an example of catching errors when using the git gem:
+
+```ruby
+begin
+ timeout_duration = 0.001 # seconds
+ repo = Git.clone('https://github.com/ruby-git/ruby-git', 'ruby-git-temp', timeout: timeout_duration)
+rescue Git::TimeoutError => e # Catch the more specific error first!
+ puts "Git clone took too long and timed out #{e}"
+rescue Git::Error => e
+ puts "Received the following error: #{e}"
+```
+
+## Specifying And Handling Timeouts
+
+The timeout feature was added in git gem version `2.0.0`.
+
+A timeout for git operations can be set either globally or for specific method calls
+that accept a `:timeout` parameter.
+
+The timeout value must be a real, non-negative `Numeric` value that specifies a
+number of seconds a `git` command will be given to complete before being sent a KILL
+signal. This library may hang if the `git` command does not terminate after receiving
+the KILL signal.
+
+When a command times out, a `Git::TimeoutError` is raised.
+
+If the timeout value is `0` or `nil`, no timeout will be enforced.
+
+If a method accepts a `:timeout` parameter and a receives a non-nil value, it will
+override the global timeout value. In this context, a value of `nil` (which is
+usually the default) will use the global timeout value and a value of `0` will turn
+off timeout enforcement for that method call no matter what the global value is.
+
+To set a global timeout, use the `Git.config` object:
+
+```ruby
+Git.config.timeout = nil # a value of nil or 0 means no timeout is enforced
+Git.config.timeout = 1.5 # can be any real, non-negative Numeric interpreted as number of seconds
+```
+
+The global timeout can be overridden for a specific method if the method accepts a
+`:timeout` parameter:
+
+```ruby
+repo_url = 'https://github.com/ruby-git/ruby-git.git'
+Git.clone(repo_url) # Use the global timeout value
+Git.clone(repo_url, timeout: nil) # Also uses the global timeout value
+Git.clone(repo_url, timeout: 0) # Do not enforce a timeout
+Git.clone(repo_url, timeout: 10.5) # Timeout after 10.5 seconds raising Git::SignaledError
+```
+
+If the command takes too long, a `Git::SignaledError` will be raised:
+
+```ruby
+begin
+ Git.clone(repo_url, timeout: 10)
+rescue Git::TimeoutError => e
+ result = e.result
+ result.class #=> Git::CommandLineResult
+ result.status #=> #<Process::Status: pid 62173 SIGKILL (signal 9)>
+ result.status.timeout? #=> true
+ result.git_cmd # The git command ran as an array of strings
+ result.stdout # The command's output to stdout until it was terminated
+ result.stderr # The command's output to stderr until it was terminated
+end
+```
+
## Examples
Here are a bunch of examples of how to use the Ruby/Git package.
Require the 'git' gem.
+
```ruby
require 'git'
```
Git env config
@@ -259,14 +379,14 @@
g.add # git add -- "."
g.add(:all=>true) # git add --all -- "."
g.add('file_path') # git add -- "file_path"
g.add(['file_path_1', 'file_path_2']) # git add -- "file_path_1" "file_path_2"
-g.remove() # git rm -f -- "."
-g.remove('file.txt') # git rm -f -- "file.txt"
-g.remove(['file.txt', 'file2.txt']) # git rm -f -- "file.txt" "file2.txt"
-g.remove('file.txt', :recursive => true) # git rm -f -r -- "file.txt"
-g.remove('file.txt', :cached => true) # git rm -f --cached -- "file.txt"
+g.remove() # git rm -f -- "."
+g.remove('file.txt') # git rm -f -- "file.txt"
+g.remove(['file.txt', 'file2.txt']) # git rm -f -- "file.txt" "file2.txt"
+g.remove('file.txt', :recursive => true) # git rm -f -r -- "file.txt"
+g.remove('file.txt', :cached => true) # git rm -f --cached -- "file.txt"
g.commit('message')
g.commit_all('message')
# Sign a commit using the gpg key configured in the user.signingkey config setting