git 1.19.0 → 2.0.0.pre1
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 +4 -4
- data/.github/workflows/continuous_integration.yml +21 -17
- data/CHANGELOG.md +18 -0
- data/README.md +49 -29
- data/RELEASING.md +49 -34
- data/git.gemspec +14 -14
- data/lib/git/command_line.rb +342 -0
- data/lib/git/failed_error.rb +2 -4
- data/lib/git/lib.rb +72 -137
- data/lib/git/version.rb +1 -1
- data/lib/git.rb +2 -0
- metadata +26 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf201a54a634864ee66f8e43866215d0c133fba4d2169ac1e0da3e5aa7bb1a2f
|
4
|
+
data.tar.gz: 38e2e3d0f2429fe458bca0218a49bd7d09707acd7d76da40cc8f9d7ce6fcfd74
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03cb58e9fc52d517d1a95584dae5c99d15532446442bac8aa6383a81770d7cc439643cd8bea04e5ae93dda8e481936ed3deebe86166fef2c4b9cd0ca3cdc8580
|
7
|
+
data.tar.gz: 2ca4de81d5a9359dc8f80d1a4ca218dafc472f5b9cb5a5b7f01c6633adbeaf8361c34e9f741147ae1948593779af9770508be35a3ef3590991e6830990a6355f
|
@@ -2,35 +2,39 @@ name: CI
|
|
2
2
|
|
3
3
|
on:
|
4
4
|
push:
|
5
|
-
branches: [master]
|
5
|
+
branches: [master,v1]
|
6
6
|
pull_request:
|
7
|
-
branches: [master]
|
7
|
+
branches: [master,v1]
|
8
8
|
workflow_dispatch:
|
9
9
|
|
10
10
|
jobs:
|
11
|
-
|
12
|
-
|
11
|
+
build:
|
12
|
+
name: Ruby ${{ matrix.ruby }} on ${{ matrix.operating-system }}
|
13
|
+
runs-on: ${{ matrix.operating-system }}
|
14
|
+
continue-on-error: ${{ matrix.experimental == 'Yes' }}
|
15
|
+
env: { JAVA_OPTS: -Djdk.io.File.enableADS=true }
|
16
|
+
|
13
17
|
strategy:
|
14
18
|
fail-fast: false
|
15
19
|
matrix:
|
16
|
-
|
20
|
+
# Only the latest versions of JRuby and TruffleRuby are tested
|
21
|
+
ruby: ["3.0", "3.1", "3.2", "3.3", "truffleruby-23.1.1", "jruby-9.4.5.0"]
|
17
22
|
operating-system: [ubuntu-latest]
|
23
|
+
experimental: [No]
|
18
24
|
include:
|
19
|
-
-
|
25
|
+
- # Building against head version of Ruby is considered experimental
|
26
|
+
ruby: head
|
20
27
|
operating-system: ubuntu-latest
|
21
|
-
|
22
|
-
operating-system: ubuntu-latest
|
23
|
-
- ruby: 2.7
|
24
|
-
operating-system: windows-latest
|
25
|
-
- ruby: jruby-head
|
26
|
-
operating-system: windows-latest
|
28
|
+
experimental: Yes
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
30
|
+
- # Only test with minimal Ruby version on Windows
|
31
|
+
ruby: 3.0
|
32
|
+
operating-system: windows-latest
|
31
33
|
|
32
|
-
|
33
|
-
|
34
|
+
- # Since JRuby on Windows is known to not work, consider this experimental
|
35
|
+
ruby: jruby-9.4.5.0
|
36
|
+
operating-system: windows-latest
|
37
|
+
experimental: Yes
|
34
38
|
|
35
39
|
steps:
|
36
40
|
- name: Checkout Code
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,24 @@
|
|
5
5
|
|
6
6
|
# Change Log
|
7
7
|
|
8
|
+
## v2.0.0.pre1 (2024-01-15)
|
9
|
+
|
10
|
+
[Full Changelog](https://github.com/ruby-git/ruby-git/compare/v1.19.1..v2.0.0.pre1)
|
11
|
+
|
12
|
+
Changes since v1.19.1:
|
13
|
+
|
14
|
+
* 7585c39 Change how the git CLI subprocess is executed (#684)
|
15
|
+
* f93e042 Update instructions for releasing a new version of the git gem (#686)
|
16
|
+
* f48930d Update minimum required version of Ruby and Git (#685)
|
17
|
+
|
18
|
+
## v1.19.1 (2024-01-13)
|
19
|
+
|
20
|
+
[Full Changelog](https://github.com/ruby-git/ruby-git/compare/v1.19.0..v1.19.1)
|
21
|
+
|
22
|
+
Changes since v1.19.0:
|
23
|
+
|
24
|
+
* f97c57c Announce the 2.0.0 pre-release (#682)
|
25
|
+
|
8
26
|
## v1.19.0 (2023-12-28)
|
9
27
|
|
10
28
|
[Full Changelog](https://github.com/ruby-git/ruby-git/compare/v1.18.0..v1.19.0)
|
data/README.md
CHANGED
@@ -5,45 +5,63 @@
|
|
5
5
|
|
6
6
|
# The Git Gem
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
[](https://badge.fury.io/rb/git)
|
9
|
+
[](https://rubydoc.info/gems/git/)
|
10
|
+
[](https://rubydoc.info/gems/git/file/CHANGELOG.md)
|
11
|
+
[](https://github.com/ruby-git/ruby-git/actions?query=workflow%3ACI)
|
12
|
+
[](https://codeclimate.com/github/ruby-git/ruby-git)
|
13
|
+
|
14
|
+
The [git gem](https://rubygems.org/gems/git) provides an API that can be used to
|
15
|
+
create, read, and manipulate Git repositories by wrapping system calls to the `git`
|
16
|
+
command line. The API can be used for working with Git in complex interactions
|
17
|
+
including branching and merging, object inspection and manipulation, history, patch
|
18
|
+
generation and more.
|
13
19
|
|
14
|
-
|
20
|
+
Get started by obtaining a repository object by:
|
15
21
|
|
16
|
-
|
22
|
+
* opening an existing working copy with [Git.open](https://rubydoc.info/gems/git/Git#open-class_method)
|
23
|
+
* initializing a new repository with [Git.init](https://rubydoc.info/gems/git/Git#init-class_method)
|
24
|
+
* cloning a repository with [Git.clone](https://rubydoc.info/gems/git/Git#clone-class_method)
|
17
25
|
|
18
|
-
|
26
|
+
Methods that can be called on a repository object are documented in [Git::Base](https://rubydoc.info/gems/git/Git/Base)
|
19
27
|
|
20
|
-
##
|
28
|
+
## v2.0.0 pre-release
|
21
29
|
|
22
|
-
|
30
|
+
git 2.0.0 is available as a pre-release version for testing! Please give it a try.
|
23
31
|
|
24
|
-
|
32
|
+
**JRuby on Windows is not yet supported by the 2.x release line. Users running JRuby
|
33
|
+
on Windows should continue to use the 1.x release line.**
|
25
34
|
|
26
|
-
|
35
|
+
The changes coming in this major release include:
|
27
36
|
|
28
|
-
*
|
29
|
-
*
|
30
|
-
*
|
37
|
+
* Create a policy of supported Ruby versions to support only non-EOL Ruby versions
|
38
|
+
* Create a policy of supported Git CLI versions (released 2020-12-25)
|
39
|
+
* Update the required Ruby version to at least 3.0 (released 2020-07-27)
|
40
|
+
* Update the required Git command line version to at least 2.28
|
41
|
+
* Update how CLI commands are called to use the [process_executer](https://github.com/main-branch/process_executer)
|
42
|
+
gem which is built on top of [Kernel.spawn](https://ruby-doc.org/3.3.0/Kernel.html#method-i-spawn).
|
43
|
+
See [PR #684](https://github.com/ruby-git/ruby-git/pull/684) for more details
|
44
|
+
on the motivation for this implementation.
|
31
45
|
|
32
|
-
|
46
|
+
The tentative plan is to release `2.0.0` near the end of March 2024 depending on
|
47
|
+
the feedback received during the pre-release period.
|
48
|
+
|
49
|
+
The `master` branch will be used for `2.x` development. If needed, fixes for `1.x`
|
50
|
+
version will be done on the `v1` branch.
|
33
51
|
|
34
52
|
## Install
|
35
53
|
|
36
|
-
|
54
|
+
Install the gem and add to the application's Gemfile by executing:
|
37
55
|
|
38
|
-
```
|
39
|
-
|
56
|
+
```shell
|
57
|
+
bundle add git
|
40
58
|
```
|
41
59
|
|
42
|
-
|
60
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
43
61
|
|
44
|
-
|
45
|
-
|
46
|
-
|
62
|
+
```shell
|
63
|
+
gem install git
|
64
|
+
```
|
47
65
|
|
48
66
|
## Major Objects
|
49
67
|
|
@@ -76,12 +94,6 @@ Pass the `--all` option to `git log` as follows:
|
|
76
94
|
|
77
95
|
Here are a bunch of examples of how to use the Ruby/Git package.
|
78
96
|
|
79
|
-
Ruby < 1.9 will require rubygems to be loaded.
|
80
|
-
|
81
|
-
```ruby
|
82
|
-
require 'rubygems'
|
83
|
-
```
|
84
|
-
|
85
97
|
Require the 'git' gem.
|
86
98
|
```ruby
|
87
99
|
require 'git'
|
@@ -395,6 +407,14 @@ g.with_temp_working(dir) do
|
|
395
407
|
end
|
396
408
|
```
|
397
409
|
|
410
|
+
## Ruby version support policy
|
411
|
+
|
412
|
+
This gem will be expected to function correctly on:
|
413
|
+
|
414
|
+
* All non-EOL versions of the MRI Ruby on Mac, Linux, and Windows
|
415
|
+
* The latest version of JRuby on Linux and Windows
|
416
|
+
* The latest version of Truffle Ruby on Linus
|
417
|
+
|
398
418
|
## License
|
399
419
|
|
400
420
|
licensed under MIT License Copyright (c) 2008 Scott Chacon. See LICENSE for further details.
|
data/RELEASING.md
CHANGED
@@ -7,64 +7,79 @@
|
|
7
7
|
|
8
8
|
Releasing a new version of the `git` gem requires these steps:
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
These instructions use an example where:
|
17
|
-
|
18
|
-
- The default branch is `master`
|
19
|
-
- The current release version is `1.5.0`
|
20
|
-
- You want to create a new *minor* release, `1.6.0`
|
10
|
+
* [Install Prerequisites](#install-prerequisites)
|
11
|
+
* [Determine the SemVer release type](#determine-the-semver-release-type)
|
12
|
+
* [Create the release](#create-the-release)
|
13
|
+
* [Review the CHANGELOG and release PR](#review-the-changelog-and-release-pr)
|
14
|
+
* [Manually merge the release PR](#manually-merge-the-release-pr)
|
15
|
+
* [Publish the git gem to RubyGems.org](#publish-the-git-gem-to-rubygemsorg)
|
21
16
|
|
22
17
|
## Install Prerequisites
|
23
18
|
|
24
19
|
The following tools need to be installed in order to create the release:
|
25
20
|
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
* [create_githhub_release](https://github.com/main-branch/create_github_release) is used to create the release
|
22
|
+
* [git](https://git-scm.com) is used by `create-github-release` to interact with the local and remote repositories
|
23
|
+
* [gh](https://cli.github.com) is used by `create-github-release` to create the release and PR in GitHub
|
29
24
|
|
30
|
-
On a Mac, these tools can be installed using [brew](https://brew.sh):
|
25
|
+
On a Mac, these tools can be installed using [gem](https://guides.rubygems.org/rubygems-basics/) and [brew](https://brew.sh):
|
31
26
|
|
32
27
|
```shell
|
28
|
+
$ gem install create_github_release
|
29
|
+
...
|
33
30
|
$ brew install git
|
34
31
|
...
|
35
32
|
$ brew install gh
|
36
33
|
...
|
37
|
-
$ brew install --cask docker
|
38
|
-
...
|
39
34
|
$
|
40
35
|
```
|
41
36
|
|
42
|
-
##
|
37
|
+
## Determine the SemVer release type
|
43
38
|
|
44
|
-
|
39
|
+
Determine the SemVer version increment that should be applied for the new release:
|
45
40
|
|
46
|
-
|
41
|
+
* `major`: when the release includes incompatible API or functional changes.
|
42
|
+
* `minor`: when the release adds functionality in a backward-compatible manner
|
43
|
+
* `patch`: when the release includes small user-facing changes that are
|
44
|
+
backward-compatible and do not introduce new functionality.
|
47
45
|
|
48
|
-
|
49
|
-
- Install development dependencies using bundle `bundle install`
|
50
|
-
- Based upon the nature of the changes, decide on the type of release: `major`, `minor`, or `patch` (in this example we will use `minor`)
|
51
|
-
- Run the release script `bundle exec create-github-release minor`
|
46
|
+
## Create the release
|
52
47
|
|
53
|
-
|
48
|
+
Create the release using the `create-github-release` command. If the release type
|
49
|
+
is `major`, the command is:
|
54
50
|
|
55
|
-
|
51
|
+
```shell
|
52
|
+
create-github-release major
|
53
|
+
```
|
56
54
|
|
57
|
-
|
55
|
+
Follow the directions given by the `create-github-release` command to finish the
|
56
|
+
release. Where the instructions given by the command differ than the instructions
|
57
|
+
below, follow the instructions given by the command.
|
58
58
|
|
59
|
-
|
59
|
+
## Review the CHANGELOG and release PR
|
60
60
|
|
61
|
-
-
|
62
|
-
|
61
|
+
The `create-github-release` command will output a link to the CHANGELOG and the PR
|
62
|
+
it created for the release. Review the CHANGELOG and have someone review and approve
|
63
|
+
the release PR.
|
63
64
|
|
64
|
-
##
|
65
|
+
## Manually merge the release PR
|
65
66
|
|
66
|
-
|
67
|
+
It is important to manually merge the PR so a separate merge commit can be avoided.
|
68
|
+
Use the commands output by the `create-github-release` which will looks like this
|
69
|
+
if you are creating a 2.0.0 release:
|
67
70
|
|
68
|
-
|
71
|
+
```shell
|
72
|
+
git checkout master
|
73
|
+
git merge --ff-only release-v2.0.0
|
74
|
+
git push
|
75
|
+
```
|
76
|
+
|
77
|
+
This will automatically close the release PR.
|
78
|
+
|
79
|
+
## Publish the git gem to RubyGems.org
|
69
80
|
|
70
|
-
|
81
|
+
Finally, publish the git gem to RubyGems.org using the following command:
|
82
|
+
|
83
|
+
```shell
|
84
|
+
rake release:rubygem_push
|
85
|
+
```
|
data/git.gemspec
CHANGED
@@ -9,35 +9,35 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.name = 'git'
|
10
10
|
s.summary = 'An API to create, read, and manipulate Git repositories'
|
11
11
|
s.description = <<~DESCRIPTION
|
12
|
-
The
|
13
|
-
Git repositories by wrapping system calls to the
|
14
|
-
used for working with Git in complex interactions
|
15
|
-
merging, object inspection and manipulation, history, patch
|
16
|
-
more.
|
12
|
+
The git gem provides an API that can be used to
|
13
|
+
create, read, and manipulate Git repositories by wrapping system calls to the git
|
14
|
+
command line. The API can be used for working with Git in complex interactions
|
15
|
+
including branching and merging, object inspection and manipulation, history, patch
|
16
|
+
generation and more.
|
17
17
|
DESCRIPTION
|
18
18
|
s.version = Git::VERSION
|
19
19
|
|
20
|
+
|
20
21
|
s.metadata['homepage_uri'] = s.homepage
|
21
22
|
s.metadata['source_code_uri'] = s.homepage
|
22
|
-
s.metadata['changelog_uri'] =
|
23
|
+
s.metadata['changelog_uri'] = "https://rubydoc.info/gems/#{s.name}/#{s.version}/file/CHANGELOG.md"
|
24
|
+
s.metadata['documentation_uri'] = "https://rubydoc.info/gems/#{s.name}/#{s.version}"
|
23
25
|
|
24
26
|
s.require_paths = ['lib']
|
25
|
-
s.required_ruby_version = '>=
|
26
|
-
s.
|
27
|
-
s.requirements = ['git 1.6.0.0, or greater']
|
27
|
+
s.required_ruby_version = '>= 3.0.0'
|
28
|
+
s.requirements = ['git 2.28.0 or greater']
|
28
29
|
|
29
30
|
s.add_runtime_dependency 'addressable', '~> 2.8'
|
31
|
+
s.add_runtime_dependency 'process_executer', '~> 0.7'
|
30
32
|
s.add_runtime_dependency 'rchardet', '~> 1.8'
|
31
33
|
|
32
|
-
s.add_development_dependency 'bump', '~> 0.10'
|
33
|
-
s.add_development_dependency 'create_github_release', '~> 0.2'
|
34
34
|
s.add_development_dependency 'minitar', '~> 0.9'
|
35
35
|
s.add_development_dependency 'mocha', '~> 2.1'
|
36
|
-
s.add_development_dependency 'rake', '~> 13.
|
37
|
-
s.add_development_dependency 'test-unit', '~> 3.
|
36
|
+
s.add_development_dependency 'rake', '~> 13.1'
|
37
|
+
s.add_development_dependency 'test-unit', '~> 3.6'
|
38
38
|
|
39
39
|
unless RUBY_PLATFORM == 'java'
|
40
|
-
s.add_development_dependency 'redcarpet', '~> 3.
|
40
|
+
s.add_development_dependency 'redcarpet', '~> 3.6'
|
41
41
|
s.add_development_dependency 'yard', '~> 0.9', '>= 0.9.28'
|
42
42
|
s.add_development_dependency 'yardstick', '~> 0.9'
|
43
43
|
end
|
@@ -0,0 +1,342 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'git/base'
|
4
|
+
require 'git/command_line_result'
|
5
|
+
require 'git/failed_error'
|
6
|
+
require 'git/signaled_error'
|
7
|
+
require 'stringio'
|
8
|
+
|
9
|
+
module Git
|
10
|
+
# Runs a git command and returns the result
|
11
|
+
#
|
12
|
+
# @api public
|
13
|
+
#
|
14
|
+
class CommandLine
|
15
|
+
# Create a Git::CommandLine object
|
16
|
+
#
|
17
|
+
# @example
|
18
|
+
# env = { 'GIT_DIR' => '/path/to/git/dir' }
|
19
|
+
# binary_path = '/usr/bin/git'
|
20
|
+
# global_opts = %w[--git-dir /path/to/git/dir]
|
21
|
+
# logger = Logger.new(STDOUT)
|
22
|
+
# cli = CommandLine.new(env, binary_path, global_opts, logger)
|
23
|
+
# cli.run('version') #=> #<Git::CommandLineResult:0x00007f9b0c0b0e00
|
24
|
+
#
|
25
|
+
# @param env [Hash<String, String>] environment variables to set
|
26
|
+
# @param global_opts [Array<String>] global options to pass to git
|
27
|
+
# @param logger [Logger] the logger to use
|
28
|
+
#
|
29
|
+
def initialize(env, binary_path, global_opts, logger)
|
30
|
+
@env = env
|
31
|
+
@binary_path = binary_path
|
32
|
+
@global_opts = global_opts
|
33
|
+
@logger = logger
|
34
|
+
end
|
35
|
+
|
36
|
+
# @attribute [r] env
|
37
|
+
#
|
38
|
+
# Variables to set (or unset) in the git command's environment
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# env = { 'GIT_DIR' => '/path/to/git/dir' }
|
42
|
+
# command_line = Git::CommandLine.new(env, '/usr/bin/git', [], Logger.new(STDOUT))
|
43
|
+
# command_line.env #=> { 'GIT_DIR' => '/path/to/git/dir' }
|
44
|
+
#
|
45
|
+
# @return [Hash<String, String>]
|
46
|
+
#
|
47
|
+
# @see https://ruby-doc.org/3.2.1/Process.html#method-c-spawn Process.spawn
|
48
|
+
# for details on how to set environment variables using the `env` parameter
|
49
|
+
#
|
50
|
+
attr_reader :env
|
51
|
+
|
52
|
+
# @attribute [r] binary_path
|
53
|
+
#
|
54
|
+
# The path to the command line binary to run
|
55
|
+
#
|
56
|
+
# @example
|
57
|
+
# binary_path = '/usr/bin/git'
|
58
|
+
# command_line = Git::CommandLine.new({}, binary_path, ['version'], Logger.new(STDOUT))
|
59
|
+
# command_line.binary_path #=> '/usr/bin/git'
|
60
|
+
#
|
61
|
+
# @return [String]
|
62
|
+
#
|
63
|
+
attr_reader :binary_path
|
64
|
+
|
65
|
+
# @attribute [r] global_opts
|
66
|
+
#
|
67
|
+
# The global options to pass to git
|
68
|
+
#
|
69
|
+
# These are options that are passed to git before the command name and
|
70
|
+
# arguments. For example, in `git --git-dir /path/to/git/dir version`, the
|
71
|
+
# global options are %w[--git-dir /path/to/git/dir].
|
72
|
+
#
|
73
|
+
# @example
|
74
|
+
# env = {}
|
75
|
+
# global_opts = %w[--git-dir /path/to/git/dir]
|
76
|
+
# logger = Logger.new(nil)
|
77
|
+
# cli = CommandLine.new(env, '/usr/bin/git', global_opts, logger)
|
78
|
+
# cli.global_opts #=> %w[--git-dir /path/to/git/dir]
|
79
|
+
#
|
80
|
+
# @return [Array<String>]
|
81
|
+
#
|
82
|
+
attr_reader :global_opts
|
83
|
+
|
84
|
+
# @attribute [r] logger
|
85
|
+
#
|
86
|
+
# The logger to use for logging git commands and results
|
87
|
+
#
|
88
|
+
# @example
|
89
|
+
# env = {}
|
90
|
+
# global_opts = %w[]
|
91
|
+
# logger = Logger.new(STDOUT)
|
92
|
+
# cli = CommandLine.new(env, '/usr/bin/git', global_opts, logger)
|
93
|
+
# cli.logger == logger #=> true
|
94
|
+
#
|
95
|
+
# @return [Logger]
|
96
|
+
#
|
97
|
+
attr_reader :logger
|
98
|
+
|
99
|
+
# Execute a git command, wait for it to finish, and return the result
|
100
|
+
#
|
101
|
+
# NORMALIZATION
|
102
|
+
#
|
103
|
+
# The command output is returned as a Unicde string containing the binary output
|
104
|
+
# from the command. If the binary output is not valid UTF-8, the output will
|
105
|
+
# cause problems because the encoding will be invalid.
|
106
|
+
#
|
107
|
+
# Normalization is a process that trys to convert the binary output to a valid
|
108
|
+
# UTF-8 string. It uses the `rchardet` gem to detect the encoding of the binary
|
109
|
+
# output and then converts it to UTF-8.
|
110
|
+
#
|
111
|
+
# Normalization is not enabled by default. Pass `normalize: true` to Git::CommandLine#run
|
112
|
+
# to enable it. Normalization will only be performed on stdout and only if the `out:`` option
|
113
|
+
# is nil or is a StringIO object. If the out: option is set to a file or other IO object,
|
114
|
+
# the normalize option will be ignored.
|
115
|
+
#
|
116
|
+
# @example Run a command and return the output
|
117
|
+
#
|
118
|
+
# cli.run('version') #=> "git version 2.39.1\n"
|
119
|
+
#
|
120
|
+
# @example The args array should be splatted into the parameter list
|
121
|
+
# args = %w[log -n 1 --oneline]
|
122
|
+
# cli.run(*args) #=> "f5baa11 beginning of Ruby/Git project\n"
|
123
|
+
#
|
124
|
+
# @example Run a command and return the chomped output
|
125
|
+
# cli.run('version', chomp: true) #=> "git version 2.39.1"
|
126
|
+
#
|
127
|
+
# @example Run a command and without normalizing the output
|
128
|
+
# cli.run('version', normalize: false) #=> "git version 2.39.1\n"
|
129
|
+
#
|
130
|
+
# @example Capture stdout in a temporary file
|
131
|
+
# require 'tempfile'
|
132
|
+
# tempfile = Tempfile.create('git') do |file|
|
133
|
+
# cli.run('version', out: file)
|
134
|
+
# file.rewind
|
135
|
+
# file.read #=> "git version 2.39.1\n"
|
136
|
+
# end
|
137
|
+
#
|
138
|
+
# @example Capture stderr in a StringIO object
|
139
|
+
# require 'stringio'
|
140
|
+
# stderr = StringIO.new
|
141
|
+
# begin
|
142
|
+
# cli.run('log', 'nonexistent-branch', err: stderr)
|
143
|
+
# rescue Git::FailedError => e
|
144
|
+
# stderr.string #=> "unknown revision or path not in the working tree.\n"
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
# @param args [Array<String>] the command line arguements to pass to git
|
148
|
+
#
|
149
|
+
# This array should be splatted into the parameter list.
|
150
|
+
#
|
151
|
+
# @param out [#write, nil] the object to write stdout to or nil to ignore stdout
|
152
|
+
#
|
153
|
+
# If this is a 'StringIO' object, then `stdout_writer.string` will be returned.
|
154
|
+
#
|
155
|
+
# In general, only specify a `stdout_writer` object when you want to redirect
|
156
|
+
# stdout to a file or some other object that responds to `#write`. The default
|
157
|
+
# behavior will return the output of the command.
|
158
|
+
#
|
159
|
+
# @param err [#write] the object to write stderr to or nil to ignore stderr
|
160
|
+
#
|
161
|
+
# If this is a 'StringIO' object and `merged_output` is `true`, then
|
162
|
+
# `stderr_writer.string` will be merged into the output returned by this method.
|
163
|
+
#
|
164
|
+
# @param normalize [Boolean] whether to normalize the output to a valid encoding
|
165
|
+
# @param chomp [Boolean] whether to chomp the output
|
166
|
+
# @param merge [Boolean] whether to merge stdout and stderr in the string returned
|
167
|
+
# @param chdir [String] the directory to run the command in
|
168
|
+
#
|
169
|
+
# @return [Git::CommandLineResult] the output of the command
|
170
|
+
#
|
171
|
+
# This result of running the command.
|
172
|
+
#
|
173
|
+
# @raise [ArgumentError] if `args` is not an array of strings
|
174
|
+
# @raise [Git::SignaledError] if the command was terminated because of an uncaught signal
|
175
|
+
# @raise [Git::FailedError] if the command returned a non-zero exitstatus
|
176
|
+
#
|
177
|
+
def run(*args, out:, err:, normalize:, chomp:, merge:, chdir: nil)
|
178
|
+
git_cmd = build_git_cmd(args)
|
179
|
+
out ||= StringIO.new
|
180
|
+
err ||= (merge ? out : StringIO.new)
|
181
|
+
status = execute(git_cmd, out, err, chdir: (chdir || :not_set))
|
182
|
+
|
183
|
+
process_result(git_cmd, status, out, err, normalize, chomp)
|
184
|
+
end
|
185
|
+
|
186
|
+
private
|
187
|
+
|
188
|
+
# Build the git command line from the available sources to send to `Process.spawn`
|
189
|
+
# @return [Array<String>]
|
190
|
+
# @api private
|
191
|
+
#
|
192
|
+
def build_git_cmd(args)
|
193
|
+
raise ArgumentError.new('The args array can not contain an array') if args.any? { |a| a.is_a?(Array) }
|
194
|
+
|
195
|
+
[binary_path, *global_opts, *args].map { |e| e.to_s }
|
196
|
+
end
|
197
|
+
|
198
|
+
# Determine the output to return in the `CommandLineResult`
|
199
|
+
#
|
200
|
+
# If the writer can return the output by calling `#string` (such as a StringIO),
|
201
|
+
# then return the result of normalizing the encoding and chomping the output
|
202
|
+
# as requested.
|
203
|
+
#
|
204
|
+
# If the writer does not support `#string`, then return nil. The output is
|
205
|
+
# assumed to be collected by the writer itself such as when the writer
|
206
|
+
# is a file instead of a StringIO.
|
207
|
+
#
|
208
|
+
# @param writer [#string] the writer to post-process
|
209
|
+
#
|
210
|
+
# @return [String, nil]
|
211
|
+
#
|
212
|
+
# @api private
|
213
|
+
#
|
214
|
+
def post_process(writer, normalize, chomp)
|
215
|
+
if writer.respond_to?(:string)
|
216
|
+
output = writer.string.dup
|
217
|
+
output = output.lines.map { |l| Git::EncodingUtils.normalize_encoding(l) }.join if normalize
|
218
|
+
output.chomp! if chomp
|
219
|
+
output
|
220
|
+
else
|
221
|
+
nil
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# Post-process all writers and return an array of the results
|
226
|
+
#
|
227
|
+
# @param writers [Array<#write>] the writers to post-process
|
228
|
+
# @param normalize [Boolean] whether to normalize the output of each writer
|
229
|
+
# @param chomp [Boolean] whether to chomp the output of each writer
|
230
|
+
#
|
231
|
+
# @return [Array<String, nil>] the output of each writer that supports `#string`
|
232
|
+
#
|
233
|
+
# @api private
|
234
|
+
#
|
235
|
+
def post_process_all(writers, normalize, chomp)
|
236
|
+
Array.new.tap do |result|
|
237
|
+
writers.each { |writer| result << post_process(writer, normalize, chomp) }
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Raise an error when there was exception while collecting the subprocess output
|
242
|
+
#
|
243
|
+
# @param git_cmd [Array<String>] the git command that was executed
|
244
|
+
# @param pipe_name [Symbol] the name of the pipe that raised the exception
|
245
|
+
# @param pipe [ProcessExecuter::MonitoredPipe] the pipe that raised the exception
|
246
|
+
#
|
247
|
+
# @raise [Git::GitExecuteError]
|
248
|
+
#
|
249
|
+
# @return [void] this method always raises an error
|
250
|
+
#
|
251
|
+
# @api private
|
252
|
+
#
|
253
|
+
def raise_pipe_error(git_cmd, pipe_name, pipe)
|
254
|
+
raise Git::GitExecuteError.new("Pipe Exception for #{git_cmd}: #{pipe_name}"), cause: pipe.exception
|
255
|
+
end
|
256
|
+
|
257
|
+
# Execute the git command and collect the output
|
258
|
+
#
|
259
|
+
# @param cmd [Array<String>] the git command to execute
|
260
|
+
# @param chdir [String] the directory to run the command in
|
261
|
+
#
|
262
|
+
# @raise [Git::GitExecuteError] if an exception was raised while collecting subprocess output
|
263
|
+
#
|
264
|
+
# @return [Process::Status] the status of the completed subprocess
|
265
|
+
#
|
266
|
+
# @api private
|
267
|
+
#
|
268
|
+
def spawn(cmd, out_writers, err_writers, chdir:)
|
269
|
+
out_pipe = ProcessExecuter::MonitoredPipe.new(*out_writers, chunk_size: 10_000)
|
270
|
+
err_pipe = ProcessExecuter::MonitoredPipe.new(*err_writers, chunk_size: 10_000)
|
271
|
+
ProcessExecuter.spawn(env, *cmd, out: out_pipe, err: err_pipe, chdir: chdir)
|
272
|
+
ensure
|
273
|
+
out_pipe.close
|
274
|
+
err_pipe.close
|
275
|
+
raise_pipe_error(cmd, :stdout, out_pipe) if out_pipe.exception
|
276
|
+
raise_pipe_error(cmd, :stderr, err_pipe) if err_pipe.exception
|
277
|
+
end
|
278
|
+
|
279
|
+
# The writers that will be used to collect stdout and stderr
|
280
|
+
#
|
281
|
+
# Additional writers could be added here if you wanted to tee output
|
282
|
+
# or send output to the terminal.
|
283
|
+
#
|
284
|
+
# @param out [#write] the object to write stdout to
|
285
|
+
# @param err [#write] the object to write stderr to
|
286
|
+
#
|
287
|
+
# @return [Array<Array<#write>, Array<#write>>] the writers for stdout and stderr
|
288
|
+
#
|
289
|
+
# @api private
|
290
|
+
#
|
291
|
+
def writers(out, err)
|
292
|
+
out_writers = [out]
|
293
|
+
err_writers = [err]
|
294
|
+
[out_writers, err_writers]
|
295
|
+
end
|
296
|
+
|
297
|
+
# Process the result of the command and return a Git::CommandLineResult
|
298
|
+
#
|
299
|
+
# Post process output, log the command and result, and raise an error if the
|
300
|
+
# command failed.
|
301
|
+
#
|
302
|
+
# @param git_cmd [Array<String>] the git command that was executed
|
303
|
+
# @param status [Process::Status] the status of the completed subprocess
|
304
|
+
# @param out [#write] the object that stdout was written to
|
305
|
+
# @param err [#write] the object that stderr was written to
|
306
|
+
# @param normalize [Boolean] whether to normalize the output of each writer
|
307
|
+
# @param chomp [Boolean] whether to chomp the output of each writer
|
308
|
+
#
|
309
|
+
# @return [Git::CommandLineResult] the result of the command to return to the caller
|
310
|
+
#
|
311
|
+
# @raise [Git::FailedError] if the command failed
|
312
|
+
# @raise [Git::SignaledError] if the command was signaled
|
313
|
+
#
|
314
|
+
# @api private
|
315
|
+
#
|
316
|
+
def process_result(git_cmd, status, out, err, normalize, chomp)
|
317
|
+
out_str, err_str = post_process_all([out, err], normalize, chomp)
|
318
|
+
logger.info { "#{git_cmd} exited with status #{status}" }
|
319
|
+
logger.debug { "stdout:\n#{out_str.inspect}\nstderr:\n#{err_str.inspect}" }
|
320
|
+
Git::CommandLineResult.new(git_cmd, status, out_str, err_str).tap do |result|
|
321
|
+
raise Git::SignaledError.new(result) if status.signaled?
|
322
|
+
raise Git::FailedError.new(result) unless status.success?
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
# Execute the git command and write the command output to out and err
|
327
|
+
#
|
328
|
+
# @param git_cmd [Array<String>] the git command to execute
|
329
|
+
# @param out [#write] the object to write stdout to
|
330
|
+
# @param err [#write] the object to write stderr to
|
331
|
+
# @param chdir [String] the directory to run the command in
|
332
|
+
#
|
333
|
+
# @return [Git::CommandLineResult] the result of the command to return to the caller
|
334
|
+
#
|
335
|
+
# @api private
|
336
|
+
#
|
337
|
+
def execute(git_cmd, out, err, chdir:)
|
338
|
+
out_writers, err_writers = writers(out, err)
|
339
|
+
spawn(git_cmd, out_writers, err_writers, chdir: chdir)
|
340
|
+
end
|
341
|
+
end
|
342
|
+
end
|
data/lib/git/failed_error.rb
CHANGED
@@ -14,20 +14,18 @@ module Git
|
|
14
14
|
class FailedError < Git::GitExecuteError
|
15
15
|
# Create a FailedError object
|
16
16
|
#
|
17
|
-
# Since this gem redirects stderr to stdout, the stdout of the process is used.
|
18
|
-
#
|
19
17
|
# @example
|
20
18
|
# `exit 1` # set $? appropriately for this example
|
21
19
|
# result = Git::CommandLineResult.new(%w[git status], $?, 'stdout', 'stderr')
|
22
20
|
# error = Git::FailedError.new(result)
|
23
21
|
# error.message #=>
|
24
|
-
# "[\"git\", \"status\"]\nstatus: pid 89784 exit 1\
|
22
|
+
# "[\"git\", \"status\"]\nstatus: pid 89784 exit 1\nstderr: \"stderr\""
|
25
23
|
#
|
26
24
|
# @param result [Git::CommandLineResult] the result of the git command including
|
27
25
|
# the git command, status, stdout, and stderr
|
28
26
|
#
|
29
27
|
def initialize(result)
|
30
|
-
super("#{result.git_cmd}\nstatus: #{result.status}\
|
28
|
+
super("#{result.git_cmd}\nstatus: #{result.status}\nstderr: #{result.stderr.inspect}")
|
31
29
|
@result = result
|
32
30
|
end
|
33
31
|
|
data/lib/git/lib.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
require 'git/failed_error'
|
2
|
+
require 'git/command_line'
|
2
3
|
require 'logger'
|
4
|
+
require 'pp'
|
5
|
+
require 'process_executer'
|
6
|
+
require 'stringio'
|
3
7
|
require 'tempfile'
|
4
8
|
require 'zlib'
|
5
9
|
require 'open3'
|
6
10
|
|
7
11
|
module Git
|
8
12
|
class Lib
|
9
|
-
|
10
|
-
@@semaphore = Mutex.new
|
11
|
-
|
12
13
|
# The path to the Git working copy. The default is '"./.git"'.
|
13
14
|
#
|
14
15
|
# @return [Pathname] the path to the Git working copy.
|
@@ -337,7 +338,19 @@ module Git
|
|
337
338
|
end
|
338
339
|
|
339
340
|
def object_contents(sha, &block)
|
340
|
-
|
341
|
+
if block_given?
|
342
|
+
Tempfile.create do |file|
|
343
|
+
# If a block is given, write the output from the process to a temporary
|
344
|
+
# file and then yield the file to the block
|
345
|
+
#
|
346
|
+
command('cat-file', "-p", sha, out: file, err: file)
|
347
|
+
file.rewind
|
348
|
+
yield file
|
349
|
+
end
|
350
|
+
else
|
351
|
+
# If a block is not given, return stdout
|
352
|
+
command('cat-file', '-p', sha)
|
353
|
+
end
|
341
354
|
end
|
342
355
|
|
343
356
|
def ls_tree(sha)
|
@@ -474,11 +487,15 @@ module Git
|
|
474
487
|
grep_opts.push('--', *opts[:path_limiter]) if opts[:path_limiter].is_a?(Array)
|
475
488
|
|
476
489
|
hsh = {}
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
490
|
+
begin
|
491
|
+
command_lines('grep', *grep_opts).each do |line|
|
492
|
+
if m = /(.*?)\:(\d+)\:(.*)/.match(line)
|
493
|
+
hsh[m[1]] ||= []
|
494
|
+
hsh[m[1]] << [m[2].to_i, m[3]]
|
495
|
+
end
|
481
496
|
end
|
497
|
+
rescue Git::FailedError => e
|
498
|
+
raise unless e.result.status.exitstatus == 1 && e.result.stderr == ''
|
482
499
|
end
|
483
500
|
hsh
|
484
501
|
end
|
@@ -865,16 +882,17 @@ module Git
|
|
865
882
|
|
866
883
|
def conflicts # :yields: file, your, their
|
867
884
|
self.unmerged.each do |f|
|
868
|
-
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
885
|
+
Tempfile.create("YOUR-#{File.basename(f)}") do |your|
|
886
|
+
command('show', ":2:#{f}", out: your)
|
887
|
+
your.close
|
888
|
+
|
889
|
+
Tempfile.create("THEIR-#{File.basename(f)}") do |their|
|
890
|
+
command('show', ":3:#{f}", out: their)
|
891
|
+
their.close
|
892
|
+
|
893
|
+
yield(f, your.path, their.path)
|
894
|
+
end
|
895
|
+
end
|
878
896
|
end
|
879
897
|
end
|
880
898
|
|
@@ -948,7 +966,7 @@ module Git
|
|
948
966
|
arr_opts << remote if remote
|
949
967
|
arr_opts << opts[:ref] if opts[:ref]
|
950
968
|
|
951
|
-
command('fetch', *arr_opts)
|
969
|
+
command('fetch', *arr_opts, merge: true)
|
952
970
|
end
|
953
971
|
|
954
972
|
def push(remote = nil, branch = nil, opts = nil)
|
@@ -1001,7 +1019,13 @@ module Git
|
|
1001
1019
|
head = File.join(@git_dir, 'refs', 'tags', tag_name)
|
1002
1020
|
return File.read(head).chomp if File.exist?(head)
|
1003
1021
|
|
1004
|
-
|
1022
|
+
begin
|
1023
|
+
command('show-ref', '--tags', '-s', tag_name)
|
1024
|
+
rescue Git::FailedError => e
|
1025
|
+
raise unless e.result.status.exitstatus == 1 && e.result.stderr == ''
|
1026
|
+
|
1027
|
+
''
|
1028
|
+
end
|
1005
1029
|
end
|
1006
1030
|
|
1007
1031
|
def repack
|
@@ -1026,15 +1050,12 @@ module Git
|
|
1026
1050
|
|
1027
1051
|
def commit_tree(tree, opts = {})
|
1028
1052
|
opts[:message] ||= "commit tree #{tree}"
|
1029
|
-
t = Tempfile.new('commit-message')
|
1030
|
-
t.write(opts[:message])
|
1031
|
-
t.close
|
1032
|
-
|
1033
1053
|
arr_opts = []
|
1034
1054
|
arr_opts << tree
|
1035
1055
|
arr_opts << '-p' << opts[:parent] if opts[:parent]
|
1036
|
-
|
1037
|
-
|
1056
|
+
Array(opts[:parents]).each { |p| arr_opts << '-p' << p } if opts[:parents]
|
1057
|
+
arr_opts << '-m' << opts[:message]
|
1058
|
+
command('commit-tree', *arr_opts)
|
1038
1059
|
end
|
1039
1060
|
|
1040
1061
|
def update_ref(ref, commit)
|
@@ -1080,7 +1101,11 @@ module Git
|
|
1080
1101
|
arr_opts << "--remote=#{opts[:remote]}" if opts[:remote]
|
1081
1102
|
arr_opts << sha
|
1082
1103
|
arr_opts << '--' << opts[:path] if opts[:path]
|
1083
|
-
|
1104
|
+
|
1105
|
+
f = File.open(file, 'wb')
|
1106
|
+
command('archive', *arr_opts, out: f)
|
1107
|
+
f.close
|
1108
|
+
|
1084
1109
|
if opts[:add_gzip]
|
1085
1110
|
file_content = File.read(file)
|
1086
1111
|
Zlib::GzipWriter.open(file) do |gz|
|
@@ -1115,7 +1140,7 @@ module Git
|
|
1115
1140
|
end
|
1116
1141
|
|
1117
1142
|
def required_command_version
|
1118
|
-
[
|
1143
|
+
[2, 28]
|
1119
1144
|
end
|
1120
1145
|
|
1121
1146
|
def meets_required_version?
|
@@ -1133,11 +1158,6 @@ module Git
|
|
1133
1158
|
|
1134
1159
|
private
|
1135
1160
|
|
1136
|
-
# Systen ENV variables involved in the git commands.
|
1137
|
-
#
|
1138
|
-
# @return [<String>] the names of the EVN variables involved in the git commands
|
1139
|
-
ENV_VARIABLE_NAMES = ['GIT_DIR', 'GIT_WORK_TREE', 'GIT_INDEX_FILE', 'GIT_SSH']
|
1140
|
-
|
1141
1161
|
def command_lines(cmd, *opts, chdir: nil)
|
1142
1162
|
cmd_op = command(cmd, *opts, chdir: chdir)
|
1143
1163
|
if cmd_op.encoding.name != "UTF-8"
|
@@ -1148,84 +1168,32 @@ module Git
|
|
1148
1168
|
op.split("\n")
|
1149
1169
|
end
|
1150
1170
|
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1171
|
+
def env_overrides
|
1172
|
+
{
|
1173
|
+
'GIT_DIR' => @git_dir,
|
1174
|
+
'GIT_WORK_TREE' => @git_work_dir,
|
1175
|
+
'GIT_INDEX_FILE' => @git_index_file,
|
1176
|
+
'GIT_SSH' => Git::Base.config.git_ssh
|
1177
|
+
}
|
1157
1178
|
end
|
1158
1179
|
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1180
|
+
def global_opts
|
1181
|
+
Array.new.tap do |global_opts|
|
1182
|
+
global_opts << "--git-dir=#{@git_dir}" if !@git_dir.nil?
|
1183
|
+
global_opts << "--work-tree=#{@git_work_dir}" if !@git_work_dir.nil?
|
1184
|
+
global_opts << '-c' << 'core.quotePath=true'
|
1185
|
+
global_opts << '-c' << 'color.ui=false'
|
1163
1186
|
end
|
1164
1187
|
end
|
1165
1188
|
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
ENV['GIT_WORK_TREE'] = @git_work_dir
|
1170
|
-
ENV['GIT_INDEX_FILE'] = @git_index_file
|
1171
|
-
ENV['GIT_SSH'] = Git::Base.config.git_ssh
|
1189
|
+
def command_line
|
1190
|
+
@command_line ||=
|
1191
|
+
Git::CommandLine.new(env_overrides, Git::Base.config.binary_path, global_opts, @logger)
|
1172
1192
|
end
|
1173
1193
|
|
1174
|
-
|
1175
|
-
|
1176
|
-
|
1177
|
-
# @param [Proc] block block to be executed within the customized environment
|
1178
|
-
def with_custom_env_variables(&block)
|
1179
|
-
@@semaphore.synchronize do
|
1180
|
-
store_git_system_env_variables()
|
1181
|
-
set_custom_git_env_variables()
|
1182
|
-
return block.call()
|
1183
|
-
end
|
1184
|
-
ensure
|
1185
|
-
restore_git_system_env_variables()
|
1186
|
-
end
|
1187
|
-
|
1188
|
-
def command(*cmd, redirect: '', chomp: true, chdir: nil, &block)
|
1189
|
-
Git::Lib.warn_if_old_command(self)
|
1190
|
-
|
1191
|
-
raise 'cmd can not include a nested array' if cmd.any? { |o| o.is_a? Array }
|
1192
|
-
|
1193
|
-
global_opts = []
|
1194
|
-
global_opts << "--git-dir=#{@git_dir}" if !@git_dir.nil?
|
1195
|
-
global_opts << "--work-tree=#{@git_work_dir}" if !@git_work_dir.nil?
|
1196
|
-
global_opts << '-c' << 'core.quotePath=true'
|
1197
|
-
global_opts << '-c' << 'color.ui=false'
|
1198
|
-
|
1199
|
-
escaped_cmd = cmd.map { |part| escape(part) }.join(' ')
|
1200
|
-
|
1201
|
-
global_opts = global_opts.map { |s| escape(s) }.join(' ')
|
1202
|
-
|
1203
|
-
git_cmd = "#{Git::Base.config.binary_path} #{global_opts} #{escaped_cmd} #{redirect} 2>&1"
|
1204
|
-
|
1205
|
-
output = nil
|
1206
|
-
|
1207
|
-
command_thread = nil;
|
1208
|
-
|
1209
|
-
status = nil
|
1210
|
-
|
1211
|
-
with_custom_env_variables do
|
1212
|
-
command_thread = Thread.new do
|
1213
|
-
output, status = run_command(git_cmd, chdir, &block)
|
1214
|
-
end
|
1215
|
-
command_thread.join
|
1216
|
-
end
|
1217
|
-
|
1218
|
-
@logger.info(git_cmd)
|
1219
|
-
@logger.debug(output)
|
1220
|
-
|
1221
|
-
if status.exitstatus > 1 || (status.exitstatus == 1 && output != '')
|
1222
|
-
result = Git::CommandLineResult.new(git_cmd, status, output, '')
|
1223
|
-
raise Git::FailedError.new(result)
|
1224
|
-
end
|
1225
|
-
|
1226
|
-
output.chomp! if output && chomp && !block_given?
|
1227
|
-
|
1228
|
-
output
|
1194
|
+
def command(*args, out: nil, err: nil, normalize: true, chomp: true, merge: false, chdir: nil)
|
1195
|
+
result = command_line.run(*args, out: out, err: err, normalize: normalize, chomp: chomp, merge: merge, chdir: chdir)
|
1196
|
+
result.stdout
|
1229
1197
|
end
|
1230
1198
|
|
1231
1199
|
# Takes the diff command line output (as Array) and parse it into a Hash
|
@@ -1291,38 +1259,5 @@ module Git
|
|
1291
1259
|
end
|
1292
1260
|
arr_opts
|
1293
1261
|
end
|
1294
|
-
|
1295
|
-
def run_command(git_cmd, chdir=nil, &block)
|
1296
|
-
block ||= Proc.new do |io|
|
1297
|
-
io.readlines.map { |l| Git::EncodingUtils.normalize_encoding(l) }.join
|
1298
|
-
end
|
1299
|
-
|
1300
|
-
opts = {}
|
1301
|
-
opts[:chdir] = File.expand_path(chdir) if chdir
|
1302
|
-
|
1303
|
-
Open3.popen2(git_cmd, opts) do |stdin, stdout, wait_thr|
|
1304
|
-
[block.call(stdout), wait_thr.value]
|
1305
|
-
end
|
1306
|
-
end
|
1307
|
-
|
1308
|
-
def escape(s)
|
1309
|
-
windows_platform? ? escape_for_windows(s) : escape_for_sh(s)
|
1310
|
-
end
|
1311
|
-
|
1312
|
-
def escape_for_sh(s)
|
1313
|
-
"'#{s && s.to_s.gsub('\'','\'"\'"\'')}'"
|
1314
|
-
end
|
1315
|
-
|
1316
|
-
def escape_for_windows(s)
|
1317
|
-
# Escape existing double quotes in s and then wrap the result with double quotes
|
1318
|
-
escaped_string = s.to_s.gsub('"','\\"')
|
1319
|
-
%Q{"#{escaped_string}"}
|
1320
|
-
end
|
1321
|
-
|
1322
|
-
def windows_platform?
|
1323
|
-
# Check if on Windows via RUBY_PLATFORM (CRuby) and RUBY_DESCRIPTION (JRuby)
|
1324
|
-
win_platform_regex = /mingw|mswin/
|
1325
|
-
RUBY_PLATFORM =~ win_platform_regex || RUBY_DESCRIPTION =~ win_platform_regex
|
1326
|
-
end
|
1327
1262
|
end
|
1328
1263
|
end
|
data/lib/git/version.rb
CHANGED
data/lib/git.rb
CHANGED
@@ -8,6 +8,7 @@ require 'git/base'
|
|
8
8
|
require 'git/branch'
|
9
9
|
require 'git/branches'
|
10
10
|
require 'git/command_line_result'
|
11
|
+
require 'git/command_line'
|
11
12
|
require 'git/config'
|
12
13
|
require 'git/diff'
|
13
14
|
require 'git/encoding_utils'
|
@@ -23,6 +24,7 @@ require 'git/remote'
|
|
23
24
|
require 'git/repository'
|
24
25
|
require 'git/signaled_error'
|
25
26
|
require 'git/status'
|
27
|
+
require 'git/signaled_error'
|
26
28
|
require 'git/stash'
|
27
29
|
require 'git/stashes'
|
28
30
|
require 'git/url'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.pre1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Chacon and others
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -25,47 +25,33 @@ dependencies:
|
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.8'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: process_executer
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0.7'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0.7'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0.10'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0.10'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: create_github_release
|
42
|
+
name: rchardet
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
45
|
- - "~>"
|
60
46
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
62
|
-
type: :
|
47
|
+
version: '1.8'
|
48
|
+
type: :runtime
|
63
49
|
prerelease: false
|
64
50
|
version_requirements: !ruby/object:Gem::Requirement
|
65
51
|
requirements:
|
66
52
|
- - "~>"
|
67
53
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
54
|
+
version: '1.8'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
56
|
name: minitar
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,42 +86,42 @@ dependencies:
|
|
100
86
|
requirements:
|
101
87
|
- - "~>"
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version: '13.
|
89
|
+
version: '13.1'
|
104
90
|
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
94
|
- - "~>"
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version: '13.
|
96
|
+
version: '13.1'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: test-unit
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
114
100
|
requirements:
|
115
101
|
- - "~>"
|
116
102
|
- !ruby/object:Gem::Version
|
117
|
-
version: '3.
|
103
|
+
version: '3.6'
|
118
104
|
type: :development
|
119
105
|
prerelease: false
|
120
106
|
version_requirements: !ruby/object:Gem::Requirement
|
121
107
|
requirements:
|
122
108
|
- - "~>"
|
123
109
|
- !ruby/object:Gem::Version
|
124
|
-
version: '3.
|
110
|
+
version: '3.6'
|
125
111
|
- !ruby/object:Gem::Dependency
|
126
112
|
name: redcarpet
|
127
113
|
requirement: !ruby/object:Gem::Requirement
|
128
114
|
requirements:
|
129
115
|
- - "~>"
|
130
116
|
- !ruby/object:Gem::Version
|
131
|
-
version: '3.
|
117
|
+
version: '3.6'
|
132
118
|
type: :development
|
133
119
|
prerelease: false
|
134
120
|
version_requirements: !ruby/object:Gem::Requirement
|
135
121
|
requirements:
|
136
122
|
- - "~>"
|
137
123
|
- !ruby/object:Gem::Version
|
138
|
-
version: '3.
|
124
|
+
version: '3.6'
|
139
125
|
- !ruby/object:Gem::Dependency
|
140
126
|
name: yard
|
141
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -171,11 +157,11 @@ dependencies:
|
|
171
157
|
- !ruby/object:Gem::Version
|
172
158
|
version: '0.9'
|
173
159
|
description: |
|
174
|
-
The
|
175
|
-
Git repositories by wrapping system calls to the
|
176
|
-
used for working with Git in complex interactions
|
177
|
-
merging, object inspection and manipulation, history, patch
|
178
|
-
more.
|
160
|
+
The git gem provides an API that can be used to
|
161
|
+
create, read, and manipulate Git repositories by wrapping system calls to the git
|
162
|
+
command line. The API can be used for working with Git in complex interactions
|
163
|
+
including branching and merging, object inspection and manipulation, history, patch
|
164
|
+
generation and more.
|
179
165
|
email: schacon@gmail.com
|
180
166
|
executables: []
|
181
167
|
extensions: []
|
@@ -203,6 +189,7 @@ files:
|
|
203
189
|
- lib/git/base/factory.rb
|
204
190
|
- lib/git/branch.rb
|
205
191
|
- lib/git/branches.rb
|
192
|
+
- lib/git/command_line.rb
|
206
193
|
- lib/git/command_line_result.rb
|
207
194
|
- lib/git/config.rb
|
208
195
|
- lib/git/diff.rb
|
@@ -232,7 +219,8 @@ licenses:
|
|
232
219
|
metadata:
|
233
220
|
homepage_uri: http://github.com/ruby-git/ruby-git
|
234
221
|
source_code_uri: http://github.com/ruby-git/ruby-git
|
235
|
-
changelog_uri:
|
222
|
+
changelog_uri: https://rubydoc.info/gems/git/2.0.0.pre1/file/CHANGELOG.md
|
223
|
+
documentation_uri: https://rubydoc.info/gems/git/2.0.0.pre1
|
236
224
|
post_install_message:
|
237
225
|
rdoc_options: []
|
238
226
|
require_paths:
|
@@ -241,15 +229,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
241
229
|
requirements:
|
242
230
|
- - ">="
|
243
231
|
- !ruby/object:Gem::Version
|
244
|
-
version:
|
232
|
+
version: 3.0.0
|
245
233
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
246
234
|
requirements:
|
247
235
|
- - ">="
|
248
236
|
- !ruby/object:Gem::Version
|
249
237
|
version: '0'
|
250
238
|
requirements:
|
251
|
-
- git
|
252
|
-
rubygems_version: 3.
|
239
|
+
- git 2.28.0 or greater
|
240
|
+
rubygems_version: 3.5.3
|
253
241
|
signing_key:
|
254
242
|
specification_version: 4
|
255
243
|
summary: An API to create, read, and manipulate Git repositories
|