git 1.8.1 → 1.10.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of git might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/continuous_integration.yml +4 -1
- data/CHANGELOG.md +16 -0
- data/CONTRIBUTING.md +8 -6
- data/Dockerfile.changelog-rs +12 -0
- data/README.md +9 -0
- data/RELEASING.md +36 -30
- data/Rakefile +12 -0
- data/lib/git/base.rb +111 -41
- data/lib/git/diff.rb +2 -2
- data/lib/git/encoding_utils.rb +33 -0
- data/lib/git/escaped_path.rb +77 -0
- data/lib/git/lib.rb +26 -33
- data/lib/git/version.rb +1 -1
- data/lib/git.rb +5 -0
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6dd58567bba3a5effab0e3d3f565f5b3891dcf056ef4df11c1521037bbe9f489
|
4
|
+
data.tar.gz: a1f8f9968a3927ce99f393805c34b0ca23941c37f27607d296eaecba9dc0f872
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1231323bde0b63677f46945800dc950a004cd854bee8c1d5a6711c8709c3dd87fb0c187f54c39c94ae07f92674f27a94b23fe3200a1799992f272c0bd84d315
|
7
|
+
data.tar.gz: 8d89a33a9cbee9357f9a4ffb568ec38506749aa81b931f9b2e862af0420c549c1738fde90e48eede6650c3202d31b9463e852eea5b358020b5561e5a60e12ef3
|
@@ -12,7 +12,7 @@ jobs:
|
|
12
12
|
strategy:
|
13
13
|
fail-fast: false
|
14
14
|
matrix:
|
15
|
-
ruby: [2.3, 2.7]
|
15
|
+
ruby: [2.3, 2.7, 3.0]
|
16
16
|
operating-system: [ubuntu-latest]
|
17
17
|
include:
|
18
18
|
- ruby: head
|
@@ -40,3 +40,6 @@ jobs:
|
|
40
40
|
|
41
41
|
- name: Run Build
|
42
42
|
run: bundle exec rake default
|
43
|
+
|
44
|
+
- name: Test Gem
|
45
|
+
run: bundle exec rake test:gem
|
data/CHANGELOG.md
CHANGED
@@ -5,6 +5,22 @@
|
|
5
5
|
|
6
6
|
# Change Log
|
7
7
|
|
8
|
+
## 1.10.1
|
9
|
+
|
10
|
+
See https://github.com/ruby-git/ruby-git/releases/tag/v1.10.1
|
11
|
+
|
12
|
+
## 1.10.0
|
13
|
+
|
14
|
+
See https://github.com/ruby-git/ruby-git/releases/tag/v1.10.0
|
15
|
+
|
16
|
+
## 1.9.1
|
17
|
+
|
18
|
+
See https://github.com/ruby-git/ruby-git/releases/tag/v1.9.1
|
19
|
+
|
20
|
+
## 1.9.0
|
21
|
+
|
22
|
+
See https://github.com/ruby-git/ruby-git/releases/tag/v1.9.0
|
23
|
+
|
8
24
|
## 1.8.1
|
9
25
|
|
10
26
|
See https://github.com/ruby-git/ruby-git/releases/tag/v1.8.1
|
data/CONTRIBUTING.md
CHANGED
@@ -78,12 +78,14 @@ In order to ensure high quality, all pull requests must meet these requirements:
|
|
78
78
|
|
79
79
|
### Unit tests
|
80
80
|
* All changes must be accompanied by new or modified unit tests
|
81
|
-
* The entire test suite must pass when `bundle exec rake
|
82
|
-
project's local working copy
|
83
|
-
|
84
|
-
### Continuous
|
85
|
-
* All tests must pass in the project's [
|
86
|
-
|
81
|
+
* The entire test suite must pass when `bundle exec rake default` is run from the
|
82
|
+
project's local working copy.
|
83
|
+
|
84
|
+
### Continuous integration
|
85
|
+
* All tests must pass in the project's [GitHub Continuous Integration build](https://github.com/ruby-git/ruby-git/actions?query=workflow%3ACI)
|
86
|
+
before the pull request will be merged.
|
87
|
+
* The [Continuous Integration workflow](https://github.com/ruby-git/ruby-git/blob/master/.github/workflows/continuous_integration.yml)
|
88
|
+
runs both `bundle exec rake default` and `bundle exec rake test:gem` from the project's [Rakefile](https://github.com/ruby-git/ruby-git/blob/master/Rakefile).
|
87
89
|
|
88
90
|
### Documentation
|
89
91
|
* New and updated public methods must have [YARD](https://yardoc.org/)
|
@@ -0,0 +1,12 @@
|
|
1
|
+
FROM rust
|
2
|
+
|
3
|
+
# Build the docker image (from this project's root directory):
|
4
|
+
# docker build --file Dockerfile.changelog-rs --tag changelog-rs .
|
5
|
+
#
|
6
|
+
# Use this image to output a changelog (from this project's root directory):
|
7
|
+
# docker run --rm --volume "$PWD:/worktree" changelog-rs v1.9.1 v1.10.0
|
8
|
+
|
9
|
+
RUN cargo install changelog-rs
|
10
|
+
WORKDIR /worktree
|
11
|
+
|
12
|
+
ENTRYPOINT ["/usr/local/cargo/bin/changelog-rs", "/worktree"]
|
data/README.md
CHANGED
@@ -146,6 +146,7 @@ g.revparse('v2.5:Makefile')
|
|
146
146
|
|
147
147
|
g.branches # returns Git::Branch objects
|
148
148
|
g.branches.local
|
149
|
+
g.current_branch
|
149
150
|
g.branches.remote
|
150
151
|
g.branches[:master].gcommit
|
151
152
|
g.branches['origin/master'].gcommit
|
@@ -225,6 +226,14 @@ g.remove('file.txt', :cached => true) # git rm -f --cached -- "file.txt"
|
|
225
226
|
g.commit('message')
|
226
227
|
g.commit_all('message')
|
227
228
|
|
229
|
+
# Sign a commit using the gpg key configured in the user.signingkey config setting
|
230
|
+
g.config('user.signingkey', '0A46826A')
|
231
|
+
g.commit('message', gpg_sign: true)
|
232
|
+
|
233
|
+
# Sign a commit using a specified gpg key
|
234
|
+
key_id = '0A46826A'
|
235
|
+
g.commit('message', gpg_sign: key_id)
|
236
|
+
|
228
237
|
g = Git.clone(repo, 'myrepo')
|
229
238
|
g.chdir do
|
230
239
|
new_file('test-file', 'blahblahblah')
|
data/RELEASING.md
CHANGED
@@ -6,9 +6,11 @@
|
|
6
6
|
# How to release a new git.gem
|
7
7
|
|
8
8
|
Releasing a new version of the `git` gem requires these steps:
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
|
10
|
+
- [How to release a new git.gem](#how-to-release-a-new-gitgem)
|
11
|
+
- [Prepare the release](#prepare-the-release)
|
12
|
+
- [Create a GitHub release](#create-a-github-release)
|
13
|
+
- [Build and release the gem](#build-and-release-the-gem)
|
12
14
|
|
13
15
|
These instructions use an example where the current release version is `1.5.0`
|
14
16
|
and the new release version to be created is `1.6.0.pre1`.
|
@@ -18,45 +20,49 @@ and the new release version to be created is `1.6.0.pre1`.
|
|
18
20
|
From a fork of ruby-git, create a PR containing changes to (1) bump the
|
19
21
|
version number, (2) update the CHANGELOG.md, and (3) tag the release.
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
23
|
+
- Bump the version number in lib/git/version.rb following [Semantic Versioning](https://semver.org)
|
24
|
+
guidelines
|
25
|
+
- Add a link in CHANGELOG.md to the release tag which will be created later
|
26
|
+
in this guide
|
27
|
+
- Create a new tag using [git-extras](https://github.com/tj/git-extras/blob/master/Commands.md#git-release)
|
28
|
+
`git release` command
|
29
|
+
- For example: `git release v1.6.0.pre1`
|
30
|
+
- These should be the only changes in the PR
|
31
|
+
- An example of these changes for `v1.6.0.pre1` can be found in [PR #435](https://github.com/ruby-git/ruby-git/pull/435)
|
32
|
+
- Get the PR reviewed, approved and merged to master.
|
31
33
|
|
32
34
|
## Create a GitHub release
|
33
35
|
|
34
36
|
On [the ruby-git releases page](https://github.com/ruby-git/ruby-git/releases),
|
35
37
|
select `Draft a new release`
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
39
|
+
- Select the tag corresponding to the version being released `v1.6.0.pre1`
|
40
|
+
- The Target should be `master`
|
41
|
+
- For the release description, use the output of [changelog-rs](https://github.com/perlun/changelog-rs)
|
42
|
+
- A Docker image is provided in [Dockerfile.changelog-rs](https://github.com/ruby-git/ruby-git/blob/master/Dockerfile.changelog-rs)
|
43
|
+
so you don't have to install changelog-rs or the Rust tool chain. To build the
|
44
|
+
Docker image, run this command from this project's root directory:
|
45
|
+
- `docker build --file Dockerfile.changelog-rs --tag changelog-rs .`
|
46
|
+
- To run the changelog-rs command using this image, run the following command
|
47
|
+
from this project's root directory (replace the tag names appropriate for the
|
48
|
+
current release):
|
49
|
+
- `docker run --rm --volume "$PWD:/worktree" changelog-rs v1.5.0 v1.6.0.pre1`
|
50
|
+
- Copy the output, omitting the tag header `## v1.6.0.pre1` and paste into
|
51
|
+
the release description
|
52
|
+
- The release description can be edited later if needed
|
53
|
+
- Select the appropriate value for `This is a pre-release`
|
54
|
+
- Since `v1.6.0.pre1` is a pre-release, check `This is a pre-release`
|
49
55
|
|
50
56
|
## Build and release the gem
|
51
57
|
|
52
58
|
Clone [ruby-git/ruby-git](https://github.com/ruby-git/ruby-git) directly (not a
|
53
59
|
fork) and ensure your local working copy is on the master branch
|
54
60
|
|
55
|
-
|
56
|
-
|
57
|
-
|
61
|
+
- Verify that you are not on a fork with the command `git remote -v`
|
62
|
+
- Verify that the version number is correct by running `rake -T` and inspecting
|
63
|
+
the output for the `release[remote]` task
|
58
64
|
|
59
65
|
Build the git gem and push it to rubygems.org with the command `rake release`
|
60
66
|
|
61
|
-
|
62
|
-
|
67
|
+
- Ensure that your `gem sources list` includes `https://rubygems.org` (in my
|
68
|
+
case, I usually have my work’s internal gem repository listed)
|
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
+
require 'English'
|
2
3
|
|
3
4
|
require "#{File.expand_path(File.dirname(__FILE__))}/lib/git/version"
|
4
5
|
|
@@ -41,4 +42,15 @@ unless RUBY_PLATFORM == 'java'
|
|
41
42
|
# default_tasks << :yardstick
|
42
43
|
end
|
43
44
|
|
45
|
+
default_tasks << :build
|
46
|
+
|
44
47
|
task default: default_tasks
|
48
|
+
|
49
|
+
desc 'Build and install the git gem and run a sanity check'
|
50
|
+
task :'test:gem' => :install do
|
51
|
+
output = `ruby -e "require 'git'; g = Git.open('.'); puts g.log.size"`.chomp
|
52
|
+
raise 'Gem test failed' unless $CHILD_STATUS.success?
|
53
|
+
raise 'Expected gem test to return an integer' unless output =~ /^\d+$/
|
54
|
+
|
55
|
+
puts 'Gem Test Succeeded'
|
56
|
+
end
|
data/lib/git/base.rb
CHANGED
@@ -12,40 +12,35 @@ module Git
|
|
12
12
|
|
13
13
|
# (see Git.bare)
|
14
14
|
def self.bare(git_dir, options = {})
|
15
|
-
|
15
|
+
normalize_paths(options, default_repository: git_dir, bare: true)
|
16
|
+
self.new(options)
|
16
17
|
end
|
17
18
|
|
18
19
|
# (see Git.clone)
|
19
20
|
def self.clone(repository, name, options = {})
|
20
|
-
|
21
|
+
new_options = Git::Lib.new(nil, options[:log]).clone(repository, name, options)
|
22
|
+
normalize_paths(new_options, bare: options[:bare] || options[:mirror])
|
23
|
+
self.new(new_options)
|
21
24
|
end
|
22
25
|
|
23
26
|
# Returns (and initialize if needed) a Git::Config instance
|
24
27
|
#
|
25
28
|
# @return [Git::Config] the current config instance.
|
26
29
|
def self.config
|
27
|
-
|
30
|
+
@@config ||= Config.new
|
28
31
|
end
|
29
32
|
|
30
33
|
# (see Git.init)
|
31
|
-
def self.init(directory, options = {})
|
32
|
-
options
|
33
|
-
options[:repository] ||= File.join(options[:working_directory], '.git')
|
34
|
-
|
35
|
-
FileUtils.mkdir_p(options[:working_directory]) if options[:working_directory] && !File.directory?(options[:working_directory])
|
34
|
+
def self.init(directory = '.', options = {})
|
35
|
+
normalize_paths(options, default_working_directory: directory, default_repository: directory, bare: options[:bare])
|
36
36
|
|
37
|
-
init_options = {
|
37
|
+
init_options = {
|
38
|
+
:bare => options[:bare],
|
39
|
+
:initial_branch => options[:initial_branch]
|
40
|
+
}
|
38
41
|
|
39
|
-
options
|
40
|
-
|
41
|
-
# Submodules have a .git *file* not a .git folder.
|
42
|
-
# This file's contents point to the location of
|
43
|
-
# where the git refs are held (In the parent repo)
|
44
|
-
if options[:working_directory] && File.file?(File.join(options[:working_directory], '.git'))
|
45
|
-
git_file = File.open('.git').read[8..-1].strip
|
46
|
-
options[:repository] = git_file
|
47
|
-
options[:index] = git_file + '/index'
|
48
|
-
end
|
42
|
+
directory = options[:bare] ? options[:repository] : options[:working_directory]
|
43
|
+
FileUtils.mkdir_p(directory) unless File.exist?(directory)
|
49
44
|
|
50
45
|
# TODO: this dance seems awkward: this creates a Git::Lib so we can call
|
51
46
|
# init so we can create a new Git::Base which in turn (ultimately)
|
@@ -63,21 +58,8 @@ module Git
|
|
63
58
|
end
|
64
59
|
|
65
60
|
# (see Git.open)
|
66
|
-
def self.open(working_dir, options={})
|
67
|
-
|
68
|
-
|
69
|
-
options[:working_directory] ||= working_dir
|
70
|
-
options[:repository] ||= File.join(options[:working_directory], '.git')
|
71
|
-
|
72
|
-
# Submodules have a .git *file* not a .git folder.
|
73
|
-
# This file's contents point to the location of
|
74
|
-
# where the git refs are held (In the parent repo)
|
75
|
-
if options[:working_directory] && File.file?(File.join(options[:working_directory], '.git'))
|
76
|
-
git_file = File.open('.git').read[8..-1].strip
|
77
|
-
options[:repository] = git_file
|
78
|
-
options[:index] = git_file + '/index'
|
79
|
-
end
|
80
|
-
|
61
|
+
def self.open(working_dir, options = {})
|
62
|
+
normalize_paths(options, default_working_directory: working_dir)
|
81
63
|
self.new(options)
|
82
64
|
end
|
83
65
|
|
@@ -137,13 +119,14 @@ module Git
|
|
137
119
|
|
138
120
|
#g.config('user.name', 'Scott Chacon') # sets value
|
139
121
|
#g.config('user.email', 'email@email.com') # sets value
|
122
|
+
#g.config('user.email', 'email@email.com', file: 'path/to/custom/config) # sets value in file
|
140
123
|
#g.config('user.name') # returns 'Scott Chacon'
|
141
124
|
#g.config # returns whole config hash
|
142
|
-
def config(name = nil, value = nil)
|
143
|
-
if
|
125
|
+
def config(name = nil, value = nil, options = {})
|
126
|
+
if name && value
|
144
127
|
# set value
|
145
|
-
lib.config_set(name, value)
|
146
|
-
elsif
|
128
|
+
lib.config_set(name, value, options)
|
129
|
+
elsif name
|
147
130
|
# return value
|
148
131
|
lib.config_get(name)
|
149
132
|
else
|
@@ -286,6 +269,7 @@ module Git
|
|
286
269
|
# options:
|
287
270
|
# :force
|
288
271
|
# :d
|
272
|
+
# :ff
|
289
273
|
#
|
290
274
|
def clean(opts = {})
|
291
275
|
self.lib.clean(opts)
|
@@ -387,7 +371,7 @@ module Git
|
|
387
371
|
# @git.pull('upstream', 'develope') # pulls from upstream/develop
|
388
372
|
#
|
389
373
|
def pull(remote='origin', branch='master')
|
390
|
-
|
374
|
+
self.lib.pull(remote, branch)
|
391
375
|
end
|
392
376
|
|
393
377
|
# returns an array of Git:Remote objects
|
@@ -566,7 +550,6 @@ module Git
|
|
566
550
|
with_working(temp_dir, &blk)
|
567
551
|
end
|
568
552
|
|
569
|
-
|
570
553
|
# runs git rev-parse to convert the objectish to a full sha
|
571
554
|
#
|
572
555
|
# @example
|
@@ -591,6 +574,93 @@ module Git
|
|
591
574
|
self.lib.branch_current
|
592
575
|
end
|
593
576
|
|
594
|
-
|
577
|
+
private
|
578
|
+
|
579
|
+
# Normalize options before they are sent to Git::Base.new
|
580
|
+
#
|
581
|
+
# Updates the options parameter by setting appropriate values for the following keys:
|
582
|
+
# * options[:working_directory]
|
583
|
+
# * options[:repository]
|
584
|
+
# * options[:index]
|
585
|
+
#
|
586
|
+
# All three values will be set to absolute paths. An exception is that
|
587
|
+
# :working_directory will be set to nil if bare is true.
|
588
|
+
#
|
589
|
+
private_class_method def self.normalize_paths(
|
590
|
+
options, default_working_directory: nil, default_repository: nil, bare: false
|
591
|
+
)
|
592
|
+
normalize_working_directory(options, default: default_working_directory, bare: bare)
|
593
|
+
normalize_repository(options, default: default_repository, bare: bare)
|
594
|
+
normalize_index(options)
|
595
|
+
end
|
596
|
+
|
597
|
+
# Normalize options[:working_directory]
|
598
|
+
#
|
599
|
+
# If working with a bare repository, set to `nil`.
|
600
|
+
# Otherwise, set to the first non-nil value of:
|
601
|
+
# 1. `options[:working_directory]`,
|
602
|
+
# 2. the `default` parameter, or
|
603
|
+
# 3. the current working directory
|
604
|
+
#
|
605
|
+
# Finally, if options[:working_directory] is a relative path, convert it to an absoluite
|
606
|
+
# path relative to the current directory.
|
607
|
+
#
|
608
|
+
private_class_method def self.normalize_working_directory(options, default:, bare: false)
|
609
|
+
working_directory =
|
610
|
+
if bare
|
611
|
+
nil
|
612
|
+
else
|
613
|
+
File.expand_path(options[:working_directory] || default || Dir.pwd)
|
614
|
+
end
|
595
615
|
|
616
|
+
options[:working_directory] = working_directory
|
617
|
+
end
|
618
|
+
|
619
|
+
# Normalize options[:repository]
|
620
|
+
#
|
621
|
+
# If working with a bare repository, set to the first non-nil value out of:
|
622
|
+
# 1. `options[:repository]`
|
623
|
+
# 2. the `default` parameter
|
624
|
+
# 3. the current working directory
|
625
|
+
#
|
626
|
+
# Otherwise, set to the first non-nil value of:
|
627
|
+
# 1. `options[:repository]`
|
628
|
+
# 2. `.git`
|
629
|
+
#
|
630
|
+
# Next, if options[:repository] refers to a *file* and not a *directory*, set
|
631
|
+
# options[:repository] to the contents of that file. This is the case when
|
632
|
+
# working with a submodule or a secondary working tree (created with git worktree
|
633
|
+
# add). In these cases the repository is actually contained/nested within the
|
634
|
+
# parent's repository directory.
|
635
|
+
#
|
636
|
+
# Finally, if options[:repository] is a relative path, convert it to an absolute
|
637
|
+
# path relative to:
|
638
|
+
# 1. the current directory if working with a bare repository or
|
639
|
+
# 2. the working directory if NOT working with a bare repository
|
640
|
+
#
|
641
|
+
private_class_method def self.normalize_repository(options, default:, bare: false)
|
642
|
+
repository =
|
643
|
+
if bare
|
644
|
+
File.expand_path(options[:repository] || default || Dir.pwd)
|
645
|
+
else
|
646
|
+
File.expand_path(options[:repository] || '.git', options[:working_directory])
|
647
|
+
end
|
648
|
+
|
649
|
+
if File.file?(repository)
|
650
|
+
repository = File.expand_path(File.open(repository).read[8..-1].strip, options[:working_directory])
|
651
|
+
end
|
652
|
+
|
653
|
+
options[:repository] = repository
|
654
|
+
end
|
655
|
+
|
656
|
+
# Normalize options[:index]
|
657
|
+
#
|
658
|
+
# If options[:index] is a relative directory, convert it to an absolute
|
659
|
+
# directory relative to the repository directory
|
660
|
+
#
|
661
|
+
private_class_method def self.normalize_index(options)
|
662
|
+
index = File.expand_path(options[:index] || 'index', options[:repository])
|
663
|
+
options[:index] = index
|
664
|
+
end
|
665
|
+
end
|
596
666
|
end
|
data/lib/git/diff.rb
CHANGED
@@ -129,8 +129,8 @@ module Git
|
|
129
129
|
final = {}
|
130
130
|
current_file = nil
|
131
131
|
@full_diff.split("\n").each do |line|
|
132
|
-
if m =
|
133
|
-
current_file = m[
|
132
|
+
if m = %r{\Adiff --git ("?)a/(.+?)\1 ("?)b/(.+?)\3\z}.match(line)
|
133
|
+
current_file = Git::EscapedPath.new(m[2]).unescape
|
134
134
|
final[current_file] = defaults.merge({:patch => line, :path => current_file})
|
135
135
|
else
|
136
136
|
if m = /^index ([0-9a-f]{4,40})\.\.([0-9a-f]{4,40})( ......)*/.match(line)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rchardet'
|
4
|
+
|
5
|
+
module Git
|
6
|
+
# Method that can be used to detect and normalize string encoding
|
7
|
+
module EncodingUtils
|
8
|
+
def self.default_encoding
|
9
|
+
__ENCODING__.name
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.best_guess_encoding
|
13
|
+
# Encoding::ASCII_8BIT.name
|
14
|
+
Encoding::UTF_8.name
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.detected_encoding(str)
|
18
|
+
CharDet.detect(str)['encoding'] || best_guess_encoding
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.encoding_options
|
22
|
+
{ invalid: :replace, undef: :replace }
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.normalize_encoding(str)
|
26
|
+
return str if str.valid_encoding? && str.encoding.name == default_encoding
|
27
|
+
|
28
|
+
return str.encode(default_encoding, str.encoding, **encoding_options) if str.valid_encoding?
|
29
|
+
|
30
|
+
str.encode(default_encoding, detected_encoding(str), **encoding_options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Git
|
4
|
+
# Represents an escaped Git path string
|
5
|
+
#
|
6
|
+
# Git commands that output paths (e.g. ls-files, diff), will escape usual
|
7
|
+
# characters in the path with backslashes in the same way C escapes control
|
8
|
+
# characters (e.g. \t for TAB, \n for LF, \\ for backslash) or bytes with values
|
9
|
+
# larger than 0x80 (e.g. octal \302\265 for "micro" in UTF-8).
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# Git::GitPath.new('\302\265').unescape # => "µ"
|
13
|
+
#
|
14
|
+
class EscapedPath
|
15
|
+
UNESCAPES = {
|
16
|
+
'a' => 0x07,
|
17
|
+
'b' => 0x08,
|
18
|
+
't' => 0x09,
|
19
|
+
'n' => 0x0a,
|
20
|
+
'v' => 0x0b,
|
21
|
+
'f' => 0x0c,
|
22
|
+
'r' => 0x0d,
|
23
|
+
'e' => 0x1b,
|
24
|
+
'\\' => 0x5c,
|
25
|
+
'"' => 0x22,
|
26
|
+
"'" => 0x27
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
attr_reader :path
|
30
|
+
|
31
|
+
def initialize(path)
|
32
|
+
@path = path
|
33
|
+
end
|
34
|
+
|
35
|
+
# Convert an escaped path to an unescaped path
|
36
|
+
def unescape
|
37
|
+
bytes = escaped_path_to_bytes(path)
|
38
|
+
str = bytes.pack('C*')
|
39
|
+
str.force_encoding(Encoding::UTF_8)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def extract_octal(path, index)
|
45
|
+
[path[index + 1..index + 4].to_i(8), 4]
|
46
|
+
end
|
47
|
+
|
48
|
+
def extract_escape(path, index)
|
49
|
+
[UNESCAPES[path[index + 1]], 2]
|
50
|
+
end
|
51
|
+
|
52
|
+
def extract_single_char(path, index)
|
53
|
+
[path[index].ord, 1]
|
54
|
+
end
|
55
|
+
|
56
|
+
def next_byte(path, index)
|
57
|
+
if path[index] == '\\' && path[index + 1] >= '0' && path[index + 1] <= '7'
|
58
|
+
extract_octal(path, index)
|
59
|
+
elsif path[index] == '\\' && UNESCAPES.include?(path[index + 1])
|
60
|
+
extract_escape(path, index)
|
61
|
+
else
|
62
|
+
extract_single_char(path, index)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def escaped_path_to_bytes(path)
|
67
|
+
index = 0
|
68
|
+
[].tap do |bytes|
|
69
|
+
while index < path.length
|
70
|
+
byte, chars_used = next_byte(path, index)
|
71
|
+
bytes << byte
|
72
|
+
index += chars_used
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/lib/git/lib.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'rchardet'
|
2
1
|
require 'tempfile'
|
3
2
|
require 'zlib'
|
4
3
|
|
@@ -71,10 +70,12 @@ module Git
|
|
71
70
|
# options:
|
72
71
|
# :bare
|
73
72
|
# :working_directory
|
73
|
+
# :initial_branch
|
74
74
|
#
|
75
75
|
def init(opts={})
|
76
76
|
arr_opts = []
|
77
77
|
arr_opts << '--bare' if opts[:bare]
|
78
|
+
arr_opts << "--initial-branch=#{opts[:initial_branch]}" if opts[:initial_branch]
|
78
79
|
|
79
80
|
command('init', arr_opts)
|
80
81
|
end
|
@@ -583,8 +584,12 @@ module Git
|
|
583
584
|
|
584
585
|
## WRITE COMMANDS ##
|
585
586
|
|
586
|
-
def config_set(name, value)
|
587
|
-
|
587
|
+
def config_set(name, value, options = {})
|
588
|
+
if options[:file].to_s.empty?
|
589
|
+
command('config', name, value)
|
590
|
+
else
|
591
|
+
command('config', '--file', options[:file], name, value)
|
592
|
+
end
|
588
593
|
end
|
589
594
|
|
590
595
|
def global_config_set(name, value)
|
@@ -642,6 +647,7 @@ module Git
|
|
642
647
|
# :date
|
643
648
|
# :no_verify
|
644
649
|
# :allow_empty_message
|
650
|
+
# :gpg_sign
|
645
651
|
#
|
646
652
|
# @param [String] message the commit message to be used
|
647
653
|
# @param [Hash] opts the commit options to be used
|
@@ -655,6 +661,14 @@ module Git
|
|
655
661
|
arr_opts << "--date=#{opts[:date]}" if opts[:date].is_a? String
|
656
662
|
arr_opts << '--no-verify' if opts[:no_verify]
|
657
663
|
arr_opts << '--allow-empty-message' if opts[:allow_empty_message]
|
664
|
+
if opts[:gpg_sign]
|
665
|
+
arr_opts <<
|
666
|
+
if opts[:gpg_sign] == true
|
667
|
+
'--gpg-sign'
|
668
|
+
else
|
669
|
+
"--gpg-sign=#{opts[:gpg_sign]}"
|
670
|
+
end
|
671
|
+
end
|
658
672
|
|
659
673
|
command('commit', arr_opts)
|
660
674
|
end
|
@@ -669,6 +683,7 @@ module Git
|
|
669
683
|
def clean(opts = {})
|
670
684
|
arr_opts = []
|
671
685
|
arr_opts << '--force' if opts[:force]
|
686
|
+
arr_opts << '-ff' if opts[:ff]
|
672
687
|
arr_opts << '-d' if opts[:d]
|
673
688
|
arr_opts << '-x' if opts[:x]
|
674
689
|
|
@@ -759,6 +774,7 @@ module Git
|
|
759
774
|
|
760
775
|
def merge(branch, message = nil, opts = {})
|
761
776
|
arr_opts = []
|
777
|
+
arr_opts << '--no-commit' if opts[:no_commit]
|
762
778
|
arr_opts << '--no-ff' if opts[:no_ff]
|
763
779
|
arr_opts << '-m' << message if message
|
764
780
|
arr_opts += [branch]
|
@@ -866,6 +882,7 @@ module Git
|
|
866
882
|
arr_opts << '--tags' if opts[:t] || opts[:tags]
|
867
883
|
arr_opts << '--prune' if opts[:p] || opts[:prune]
|
868
884
|
arr_opts << '--unshallow' if opts[:unshallow]
|
885
|
+
arr_opts << '--depth' << opts[:depth] if opts[:depth]
|
869
886
|
|
870
887
|
command('fetch', arr_opts)
|
871
888
|
end
|
@@ -1067,7 +1084,8 @@ module Git
|
|
1067
1084
|
global_opts = []
|
1068
1085
|
global_opts << "--git-dir=#{@git_dir}" if !@git_dir.nil?
|
1069
1086
|
global_opts << "--work-tree=#{@git_work_dir}" if !@git_work_dir.nil?
|
1070
|
-
global_opts << [
|
1087
|
+
global_opts << %w[-c core.quotePath=true]
|
1088
|
+
global_opts << %w[-c color.ui=false]
|
1071
1089
|
|
1072
1090
|
opts = [opts].flatten.map {|s| escape(s) }.join(' ')
|
1073
1091
|
|
@@ -1158,35 +1176,10 @@ module Git
|
|
1158
1176
|
arr_opts
|
1159
1177
|
end
|
1160
1178
|
|
1161
|
-
def default_encoding
|
1162
|
-
__ENCODING__.name
|
1163
|
-
end
|
1164
|
-
|
1165
|
-
def best_guess_encoding
|
1166
|
-
# Encoding::ASCII_8BIT.name
|
1167
|
-
Encoding::UTF_8.name
|
1168
|
-
end
|
1169
|
-
|
1170
|
-
def detected_encoding(str)
|
1171
|
-
CharDet.detect(str)['encoding'] || best_guess_encoding
|
1172
|
-
end
|
1173
|
-
|
1174
|
-
def encoding_options
|
1175
|
-
{ invalid: :replace, undef: :replace }
|
1176
|
-
end
|
1177
|
-
|
1178
|
-
def normalize_encoding(str)
|
1179
|
-
return str if str.valid_encoding? && str.encoding.name == default_encoding
|
1180
|
-
|
1181
|
-
return str.encode(default_encoding, str.encoding, **encoding_options) if str.valid_encoding?
|
1182
|
-
|
1183
|
-
str.encode(default_encoding, detected_encoding(str), **encoding_options)
|
1184
|
-
end
|
1185
|
-
|
1186
1179
|
def run_command(git_cmd, &block)
|
1187
1180
|
return IO.popen(git_cmd, &block) if block_given?
|
1188
1181
|
|
1189
|
-
`#{git_cmd}`.lines.map { |l| normalize_encoding(l) }.join
|
1182
|
+
`#{git_cmd}`.lines.map { |l| Git::EncodingUtils.normalize_encoding(l) }.join
|
1190
1183
|
end
|
1191
1184
|
|
1192
1185
|
def escape(s)
|
@@ -1198,8 +1191,9 @@ module Git
|
|
1198
1191
|
end
|
1199
1192
|
|
1200
1193
|
def escape_for_windows(s)
|
1201
|
-
#
|
1202
|
-
|
1194
|
+
# Escape existing double quotes in s and then wrap the result with double quotes
|
1195
|
+
escaped_string = s.to_s.gsub('"','\\"')
|
1196
|
+
%Q{"#{escaped_string}"}
|
1203
1197
|
end
|
1204
1198
|
|
1205
1199
|
def windows_platform?
|
@@ -1207,6 +1201,5 @@ module Git
|
|
1207
1201
|
win_platform_regex = /mingw|mswin/
|
1208
1202
|
RUBY_PLATFORM =~ win_platform_regex || RUBY_DESCRIPTION =~ win_platform_regex
|
1209
1203
|
end
|
1210
|
-
|
1211
1204
|
end
|
1212
1205
|
end
|
data/lib/git/version.rb
CHANGED
data/lib/git.rb
CHANGED
@@ -9,6 +9,8 @@ require 'git/branch'
|
|
9
9
|
require 'git/branches'
|
10
10
|
require 'git/config'
|
11
11
|
require 'git/diff'
|
12
|
+
require 'git/encoding_utils'
|
13
|
+
require 'git/escaped_path'
|
12
14
|
require 'git/index'
|
13
15
|
require 'git/lib'
|
14
16
|
require 'git/log'
|
@@ -212,6 +214,9 @@ module Git
|
|
212
214
|
# `"#{directory}/.git"`, create a bare repository at `"#{directory}"`.
|
213
215
|
# See [what is a bare repository?](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefbarerepositoryabarerepository).
|
214
216
|
#
|
217
|
+
# @option options [String] :initial_branch Use the specified name for the
|
218
|
+
# initial branch in the newly created repository.
|
219
|
+
#
|
215
220
|
# @option options [Pathname] :repository the path to put the newly initialized
|
216
221
|
# Git repository. The default for non-bare repository is `"#{directory}/.git"`.
|
217
222
|
#
|
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: 1.
|
4
|
+
version: 1.10.1
|
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: 2022-01-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rchardet
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- ".yardopts"
|
126
126
|
- CHANGELOG.md
|
127
127
|
- CONTRIBUTING.md
|
128
|
+
- Dockerfile.changelog-rs
|
128
129
|
- Gemfile
|
129
130
|
- ISSUE_TEMPLATE.md
|
130
131
|
- LICENSE
|
@@ -142,6 +143,8 @@ files:
|
|
142
143
|
- lib/git/branches.rb
|
143
144
|
- lib/git/config.rb
|
144
145
|
- lib/git/diff.rb
|
146
|
+
- lib/git/encoding_utils.rb
|
147
|
+
- lib/git/escaped_path.rb
|
145
148
|
- lib/git/index.rb
|
146
149
|
- lib/git/lib.rb
|
147
150
|
- lib/git/log.rb
|
@@ -179,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
179
182
|
version: '0'
|
180
183
|
requirements:
|
181
184
|
- git 1.6.0.0, or greater
|
182
|
-
rubygems_version: 3.1.
|
185
|
+
rubygems_version: 3.1.6
|
183
186
|
signing_key:
|
184
187
|
specification_version: 4
|
185
188
|
summary: An API to create, read, and manipulate Git repositories
|