git 1.19.0 → 2.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/git.svg)](https://badge.fury.io/rb/git)
|
9
|
+
[![Documentation](https://img.shields.io/badge/Documentation-Latest-green)](https://rubydoc.info/gems/git/)
|
10
|
+
[![Change Log](https://img.shields.io/badge/CHANGELOG-Latest-green)](https://rubydoc.info/gems/git/file/CHANGELOG.md)
|
11
|
+
[![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)
|
12
|
+
[![Code Climate](https://codeclimate.com/github/ruby-git/ruby-git.png)](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
|