gitw 0.3.0
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 +7 -0
- data/.rubocop.yml +27 -0
- data/Gemfile +5 -0
- data/README.md +23 -0
- data/Rakefile +32 -0
- data/lib/gitw/exec.rb +88 -0
- data/lib/gitw/git/remote_ref.rb +79 -0
- data/lib/gitw/git/status.rb +101 -0
- data/lib/gitw/git_error.rb +7 -0
- data/lib/gitw/git_exe.rb +279 -0
- data/lib/gitw/git_opts.rb +101 -0
- data/lib/gitw/repository.rb +1 -0
- data/lib/gitw/version.rb +5 -0
- data/lib/gitw.rb +28 -0
- data/scripts/console +15 -0
- data/scripts/setup +8 -0
- metadata +227 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 64596c0a6c9d3e0f03c3735cf4f3208267b66676ffcdef572416e46c993652ae
|
4
|
+
data.tar.gz: f4cc05abf07727acd192a4a92af62f4436921d89b7664c883d4ed5cfa738d8a1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 802bd89fb34f1c8a04475a4b417a841b8ef27ed42ead9f495d691fa5cfadfe95249066d43dbfc9f99c262d257960f66dafb47d48c57a4f3d26eaf371994ff2b9
|
7
|
+
data.tar.gz: a7baf4ab64fcaa695d9137ddf9be34aa4ae8098c828b8c7325ef5c437316a8f079087f4bdd22ada2dfbd730649492c95473f2dba9b820fdbf494b3178e0ed097
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.6
|
3
|
+
NewCops: enable
|
4
|
+
|
5
|
+
require:
|
6
|
+
- rubocop-minitest
|
7
|
+
- rubocop-rake
|
8
|
+
|
9
|
+
# Style/StringLiterals:
|
10
|
+
# Enabled: true
|
11
|
+
# EnforcedStyle: double_quotes
|
12
|
+
|
13
|
+
# Style/StringLiteralsInInterpolation:
|
14
|
+
# Enabled: true
|
15
|
+
# EnforcedStyle: double_quotes
|
16
|
+
|
17
|
+
Layout/LineLength:
|
18
|
+
Max: 100
|
19
|
+
|
20
|
+
Metrics/BlockLength:
|
21
|
+
Exclude:
|
22
|
+
- gitw.gemspec
|
23
|
+
- test/**/*.rb
|
24
|
+
|
25
|
+
Metrics/MethodLength:
|
26
|
+
Exclude:
|
27
|
+
- test/**/*.rb
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Gitw
|
2
|
+
|
3
|
+
Gem to wrab git command.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Manual install, by executing:
|
8
|
+
|
9
|
+
$ gem install gitw
|
10
|
+
|
11
|
+
Add to Gemfile with:
|
12
|
+
|
13
|
+
$ bundle add gitw
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
TODO: Write usage instructions here
|
18
|
+
|
19
|
+
## Contributing
|
20
|
+
|
21
|
+
Bug reports and pull requests are welcome on
|
22
|
+
- GitLab at https://gitlab.com/[USERNAME]/gitw
|
23
|
+
- GitHub at https://github.com/[USERNAME]/gitw
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
require 'bump/tasks'
|
6
|
+
|
7
|
+
require 'rake/testtask'
|
8
|
+
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs.push('lib', 'test')
|
11
|
+
t.test_files = FileList['test/**/test_*.rb', 'test/**/*_test.rb',]
|
12
|
+
t.verbose = true
|
13
|
+
t.warning = true
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'Generates a coverage report'
|
17
|
+
task :coverage do
|
18
|
+
ENV['COVERAGE'] = 'true'
|
19
|
+
Rake::Task['test'].execute
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'rubocop/rake_task'
|
23
|
+
RuboCop::RakeTask.new
|
24
|
+
|
25
|
+
require 'yard'
|
26
|
+
|
27
|
+
YARD::Rake::YardocTask.new do |t|
|
28
|
+
t.files = ['lib/**/*.rb']
|
29
|
+
t.stats_options = ['--list-undoc']
|
30
|
+
end
|
31
|
+
|
32
|
+
task default: %i[test rubocop]
|
data/lib/gitw/exec.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
require 'open3'
|
5
|
+
|
6
|
+
module Gitw
|
7
|
+
# exec
|
8
|
+
class Exec
|
9
|
+
def initialize(*commands, **options)
|
10
|
+
@commands = commands
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def exec
|
15
|
+
# puts "EXEC (#{Dir.pwd})> #{commands} #{options}"
|
16
|
+
stdout, stderr, exit_status = Open3.capture3(*commands, **options)
|
17
|
+
|
18
|
+
ExecResult.new(commands: commands,
|
19
|
+
options: options,
|
20
|
+
status: exit_status,
|
21
|
+
stdout: stdout,
|
22
|
+
stderr: stderr)
|
23
|
+
rescue StandardError => e
|
24
|
+
ExecResult.from_exception(e, commands: commands, options: options)
|
25
|
+
end
|
26
|
+
|
27
|
+
def commands
|
28
|
+
@commands.flatten.compact
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :options
|
32
|
+
end
|
33
|
+
|
34
|
+
# exec result
|
35
|
+
class ExecResult
|
36
|
+
extend Forwardable
|
37
|
+
|
38
|
+
def_delegators :@status, :exitstatus, :success?, :exited?, :signaled?, :pid
|
39
|
+
|
40
|
+
attr_reader :commands, :options, :status, :stdout, :stderr
|
41
|
+
|
42
|
+
def initialize(commands:, options:, status:, stdout:, stderr:)
|
43
|
+
@commands = commands
|
44
|
+
@options = options
|
45
|
+
@status = status
|
46
|
+
@stdout = stdout
|
47
|
+
@stderr = stderr
|
48
|
+
end
|
49
|
+
|
50
|
+
def raise_on_failure(exception = RuntimeError)
|
51
|
+
return if success?
|
52
|
+
|
53
|
+
raise exception, "git exited #{exitstatus}: #{stderr}"
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.from_exception(exception, commands: nil, options: nil)
|
57
|
+
exception.extend AsAProcessStatus
|
58
|
+
new(commands: commands,
|
59
|
+
options: options,
|
60
|
+
status: exception,
|
61
|
+
stdout: nil,
|
62
|
+
stderr: "Exception: #{exception}")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# behavior to simulate
|
67
|
+
module AsAProcessStatus
|
68
|
+
def exitstatus
|
69
|
+
-2
|
70
|
+
end
|
71
|
+
|
72
|
+
def success?
|
73
|
+
false
|
74
|
+
end
|
75
|
+
|
76
|
+
def exited?
|
77
|
+
true
|
78
|
+
end
|
79
|
+
|
80
|
+
def signaled?
|
81
|
+
false
|
82
|
+
end
|
83
|
+
|
84
|
+
def pid
|
85
|
+
-2
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitw
|
4
|
+
module Git
|
5
|
+
# encapsulate git remote references
|
6
|
+
class RemoteRefs
|
7
|
+
def initialize(refs)
|
8
|
+
@refs = refs.compact
|
9
|
+
|
10
|
+
@index_name = {}
|
11
|
+
@index_url = {}
|
12
|
+
|
13
|
+
@refs.each do |ref|
|
14
|
+
@index_name[ref.name] = ref
|
15
|
+
@index_url[ref.url] ||= []
|
16
|
+
@index_url[ref.url] << ref
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def by_name(name)
|
21
|
+
@index_name[name]
|
22
|
+
end
|
23
|
+
|
24
|
+
def by_url(url)
|
25
|
+
@index_url[url]
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.parse(output)
|
29
|
+
return new unless output
|
30
|
+
|
31
|
+
refs = output.each_line.with_object({}) do |entry, refs_store|
|
32
|
+
remote = RemoteRef.parse(entry)
|
33
|
+
next unless remote
|
34
|
+
|
35
|
+
refs_store[remote.name] ||= remote
|
36
|
+
refs_store[remote.name].update(remote)
|
37
|
+
end
|
38
|
+
new(refs.values)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# encapsulate git remote reference entry
|
43
|
+
class RemoteRef
|
44
|
+
REMOTE_LINE_RE = /^(?<name>\w+)
|
45
|
+
\s+
|
46
|
+
(?<url>[^\s]+)
|
47
|
+
\s+
|
48
|
+
\((?<mode>fetch|push)\)$/x.freeze
|
49
|
+
|
50
|
+
attr_reader :name, :fetch, :push
|
51
|
+
|
52
|
+
def initialize(name, fetch: nil, push: nil)
|
53
|
+
@name = name
|
54
|
+
@fetch = fetch
|
55
|
+
@push = push
|
56
|
+
end
|
57
|
+
|
58
|
+
def url
|
59
|
+
fetch || push
|
60
|
+
end
|
61
|
+
|
62
|
+
def update(other_ref)
|
63
|
+
return self if self == other_ref
|
64
|
+
return self if name != other_ref.name
|
65
|
+
|
66
|
+
@fetch = other_ref.fetch || @fetch
|
67
|
+
@push = other_ref.push || @push
|
68
|
+
self
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.parse(ref_line)
|
72
|
+
return unless (match = REMOTE_LINE_RE.match(ref_line.strip))
|
73
|
+
|
74
|
+
new(match[:name],
|
75
|
+
match[:mode].to_sym => match[:url])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitw
|
4
|
+
module Git
|
5
|
+
# encapsulate git porcelain status output
|
6
|
+
class Status
|
7
|
+
def initialize(files)
|
8
|
+
@files = files.compact
|
9
|
+
|
10
|
+
@index_map = {}
|
11
|
+
@workingtree_map = {}
|
12
|
+
@untracked_map = {}
|
13
|
+
@files.each do |file|
|
14
|
+
@index_map[file.path] = file if file.index_changed?
|
15
|
+
@workingtree_map[file.path] = file if file.workingtree_changed?
|
16
|
+
@untracked_map[file.path] = file if file.untracked?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def changed?(filename)
|
21
|
+
@index_map[filename] || @workingtree_map[filename]
|
22
|
+
end
|
23
|
+
|
24
|
+
def untracked?(filename)
|
25
|
+
@untracked_map[filename]
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.parse(output)
|
29
|
+
return new unless output
|
30
|
+
|
31
|
+
files = output.each_line.with_object([]) do |entry, files_store|
|
32
|
+
files_store << StatusFile.parse(entry)
|
33
|
+
end
|
34
|
+
new(files)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# encapsulate git status file entry
|
39
|
+
class StatusFile
|
40
|
+
STATUS_LINE_RE = /^(?<index_status>.)
|
41
|
+
(?<workingtree_status>.)
|
42
|
+
\s
|
43
|
+
(?:(?<orig_path>.*?)\s->\s)?
|
44
|
+
(?<path>.*)$/x.freeze
|
45
|
+
|
46
|
+
STATUS_MAP = {
|
47
|
+
' ' => :unmodified,
|
48
|
+
'M' => :modified,
|
49
|
+
'T' => :file_type_changed,
|
50
|
+
'A' => :added,
|
51
|
+
'D' => :deleted,
|
52
|
+
'R' => :renamed,
|
53
|
+
'C' => :copied,
|
54
|
+
'U' => :updated,
|
55
|
+
'?' => :untracked,
|
56
|
+
'!' => :ignored
|
57
|
+
}.freeze
|
58
|
+
|
59
|
+
attr_reader :path
|
60
|
+
|
61
|
+
def initialize(path, index_status: nil, workingtree_status: nil, orig_path: nil)
|
62
|
+
@path = path
|
63
|
+
@index_status = index_status
|
64
|
+
@workingtree_status = workingtree_status
|
65
|
+
@orig_path = orig_path
|
66
|
+
end
|
67
|
+
|
68
|
+
def index_changed?
|
69
|
+
return false if STATUS_MAP[@index_status] == :unmodified
|
70
|
+
return false if STATUS_MAP[@index_status] == :ignored
|
71
|
+
return false if STATUS_MAP[@index_status] == :untracked
|
72
|
+
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
def workingtree_changed?
|
77
|
+
return false if STATUS_MAP[@workingtree_status] == :unmodified
|
78
|
+
return false if STATUS_MAP[@workingtree_status] == :ignored
|
79
|
+
return false if STATUS_MAP[@workingtree_status] == :untracked
|
80
|
+
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
84
|
+
def untracked?
|
85
|
+
return true if STATUS_MAP[@index_status] == :untracked
|
86
|
+
return true if STATUS_MAP[@workingtree_status] == :untracked
|
87
|
+
|
88
|
+
false
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.parse(status_line)
|
92
|
+
return unless (match = STATUS_LINE_RE.match(status_line))
|
93
|
+
|
94
|
+
new(match[:path],
|
95
|
+
index_status: match[:index_status],
|
96
|
+
workingtree_status: match[:workingtree_status],
|
97
|
+
orig_path: match[:orig_path])
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/gitw/git_exe.rb
ADDED
@@ -0,0 +1,279 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'exec'
|
4
|
+
require_relative 'git_error'
|
5
|
+
require_relative 'git_opts'
|
6
|
+
require_relative 'git/status'
|
7
|
+
require_relative 'git/remote_ref'
|
8
|
+
|
9
|
+
# rubocop:disable Metrics/ClassLength, Metrics/MethodLength, Naming/PredicateName
|
10
|
+
module Gitw
|
11
|
+
# git executable wrapper
|
12
|
+
class GitExe
|
13
|
+
def initialize(options: nil, git_bin: nil, env: ENV)
|
14
|
+
@options = options
|
15
|
+
@git_bin = git_bin
|
16
|
+
@env = env
|
17
|
+
end
|
18
|
+
|
19
|
+
def git_bin
|
20
|
+
@git_bin || @env['GIT_BIN'] || self.class.git_bin
|
21
|
+
end
|
22
|
+
|
23
|
+
def exec(*cmds, **opts)
|
24
|
+
result = Exec.new(git_bin, *cmds, **opts).exec
|
25
|
+
result.raise_on_failure(Gitw::GitError)
|
26
|
+
result.stdout
|
27
|
+
rescue StandardError => e
|
28
|
+
raise Gitw::GitError, e.to_s
|
29
|
+
end
|
30
|
+
|
31
|
+
def git_opts(options = nil)
|
32
|
+
GitOpts.new
|
33
|
+
.allow(:c, short: '-c', with_arg: true, multiple: true)
|
34
|
+
.allow(:git_dir, long: '--git-dir', with_arg: true)
|
35
|
+
.allow(:work_tree, long: '--work-tree', with_arg: true)
|
36
|
+
.allow(:dir, short: '-C', with_arg: true)
|
37
|
+
.allow(:version, short: '-v', long: '--version')
|
38
|
+
.add(:c, 'core.quotePath=true')
|
39
|
+
.add(:c, 'color.ui=false')
|
40
|
+
.from(@options)
|
41
|
+
.from(options)
|
42
|
+
end
|
43
|
+
|
44
|
+
# version
|
45
|
+
|
46
|
+
def version
|
47
|
+
version_git_opts = git_opts.add(:version)
|
48
|
+
version = exec(*version_git_opts)
|
49
|
+
version.strip
|
50
|
+
rescue StandardError
|
51
|
+
nil
|
52
|
+
end
|
53
|
+
|
54
|
+
# init
|
55
|
+
|
56
|
+
def init_opts(options = nil)
|
57
|
+
GitOpts.new
|
58
|
+
.allow(:quiet, short: '-q', long: '--quiet')
|
59
|
+
.allow(:bare, long: '--bare')
|
60
|
+
.allow(:init_branch, short: '-b', with_arg: true)
|
61
|
+
.from(@options)
|
62
|
+
.from(options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def init(*args, git_options: nil, **options)
|
66
|
+
init_git_options = git_opts(git_options)
|
67
|
+
init_options = init_opts(options)
|
68
|
+
exec(*init_git_options, 'init', *init_options, *args)
|
69
|
+
end
|
70
|
+
|
71
|
+
# clone
|
72
|
+
|
73
|
+
def clone_opts(options = nil)
|
74
|
+
GitOpts.new
|
75
|
+
.allow(:verbose, short: '-v', long: '--verbose')
|
76
|
+
.allow(:quiet, short: '-q', long: '--quiet')
|
77
|
+
.allow(:no_checkout, long: '--no-checkout')
|
78
|
+
.allow(:bare, long: '--bare')
|
79
|
+
.allow(:mirror, long: '--mirror')
|
80
|
+
.allow(:depth, long: '--depth', with_arg: true)
|
81
|
+
.from(@options)
|
82
|
+
.from(options)
|
83
|
+
end
|
84
|
+
|
85
|
+
def clone(from, to, git_options: nil, **options)
|
86
|
+
clone_git_options = git_opts(git_options)
|
87
|
+
clone_options = clone_opts(options)
|
88
|
+
exec(*clone_git_options, 'clone', *clone_options, from, to)
|
89
|
+
end
|
90
|
+
|
91
|
+
# rev-parse
|
92
|
+
|
93
|
+
def rev_parse_opts(options = nil)
|
94
|
+
GitOpts.new
|
95
|
+
.allow(:git_dir, long: '--git-dir')
|
96
|
+
.allow(:git_common_dir, long: '--git-common-dir')
|
97
|
+
.allow(:show_toplevel, long: '--show-toplevel')
|
98
|
+
.allow(:absolute_git_dir, long: '--absolute-git-dir')
|
99
|
+
.allow(:is_inside_git_dir, long: '--is-inside-git-dir')
|
100
|
+
.allow(:is_inside_work_tree, long: '--is-inside-work-tree')
|
101
|
+
.allow(:is_bare_repository, long: '--is-bare-repository')
|
102
|
+
.allow(:is_shallow_repository, long: '--is-shallow-repository')
|
103
|
+
.from(@options)
|
104
|
+
.from(options)
|
105
|
+
end
|
106
|
+
|
107
|
+
def rev_parse(*args, git_options: nil, **options)
|
108
|
+
rev_parse_git_options = git_opts(git_options)
|
109
|
+
rev_parse_options = rev_parse_opts(options)
|
110
|
+
exec(*rev_parse_git_options, 'rev-parse', *rev_parse_options, *args)
|
111
|
+
end
|
112
|
+
|
113
|
+
def git_dir(git_options: nil)
|
114
|
+
git_dir = rev_parse(git_options: git_options, git_dir: nil)
|
115
|
+
git_dir.strip
|
116
|
+
end
|
117
|
+
|
118
|
+
def toplevel(git_options: nil)
|
119
|
+
git_dir = rev_parse(git_options: git_options, show_toplevel: nil)
|
120
|
+
git_dir.strip
|
121
|
+
end
|
122
|
+
|
123
|
+
def is_inside_git_dir(git_options: nil)
|
124
|
+
status = rev_parse(git_options: git_options, is_inside_git_dir: nil)
|
125
|
+
status.strip.downcase == 'true'
|
126
|
+
end
|
127
|
+
|
128
|
+
def is_inside_work_tree(git_options: nil)
|
129
|
+
status = rev_parse(git_options: git_options, is_inside_work_tree: nil)
|
130
|
+
status.strip.downcase == 'true'
|
131
|
+
end
|
132
|
+
|
133
|
+
def is_bare_repository(git_options: nil)
|
134
|
+
status = rev_parse(git_options: git_options, is_bare_repository: nil)
|
135
|
+
status.strip.downcase == 'true'
|
136
|
+
end
|
137
|
+
|
138
|
+
def is_shallow_repository(git_options: nil)
|
139
|
+
status = rev_parse(git_options: git_options, is_shallow_repository: nil)
|
140
|
+
status.strip.downcase == 'true'
|
141
|
+
end
|
142
|
+
|
143
|
+
# status
|
144
|
+
|
145
|
+
def status_opts(options = nil)
|
146
|
+
GitOpts.new
|
147
|
+
.allow(:porcelain, long: '--porcelain')
|
148
|
+
.from(@options)
|
149
|
+
.from(options)
|
150
|
+
end
|
151
|
+
|
152
|
+
def status(*args, git_options: nil, **options)
|
153
|
+
status_git_options = git_opts(git_options)
|
154
|
+
status_options = status_opts(options)
|
155
|
+
exec(*status_git_options, 'status', *status_options, *args)
|
156
|
+
end
|
157
|
+
|
158
|
+
def status_obj(*args, git_options: nil, **options)
|
159
|
+
Git::Status.parse(status(*args, git_options: git_options, **options.merge(porcelain: true)))
|
160
|
+
end
|
161
|
+
|
162
|
+
# add
|
163
|
+
|
164
|
+
def add_opts(options = nil)
|
165
|
+
GitOpts.new
|
166
|
+
.from(@options)
|
167
|
+
.from(options)
|
168
|
+
end
|
169
|
+
|
170
|
+
def add(*files, git_options: nil, **options)
|
171
|
+
add_git_options = git_opts(git_options)
|
172
|
+
add_options = add_opts(options)
|
173
|
+
|
174
|
+
exec(*add_git_options, 'add', *add_options, *files)
|
175
|
+
end
|
176
|
+
|
177
|
+
# commit
|
178
|
+
|
179
|
+
def commit_opts(options = nil)
|
180
|
+
GitOpts.new
|
181
|
+
.allow(:all, short: '-a')
|
182
|
+
.allow(:message, short: '-m', long: '--message', with_arg: true)
|
183
|
+
.from(@options)
|
184
|
+
.from(options)
|
185
|
+
end
|
186
|
+
|
187
|
+
def commit(*args, git_options: nil, **options)
|
188
|
+
commit_git_options = git_opts(git_options)
|
189
|
+
commit_options = commit_opts(options)
|
190
|
+
|
191
|
+
exec(*commit_git_options, 'commit', *commit_options, *args)
|
192
|
+
end
|
193
|
+
|
194
|
+
# fetch
|
195
|
+
|
196
|
+
def fetch_opts(options = nil)
|
197
|
+
GitOpts.new
|
198
|
+
.allow(:all, long: '--all')
|
199
|
+
.allow(:tags, short: '-t', long: '--tags')
|
200
|
+
.from(@options)
|
201
|
+
.from(options)
|
202
|
+
end
|
203
|
+
|
204
|
+
def fetch(*args, git_options: nil, **options)
|
205
|
+
fetch_git_options = git_opts(git_options)
|
206
|
+
fetch_options = fetch_opts(options)
|
207
|
+
|
208
|
+
exec(*fetch_git_options, 'fetch', *fetch_options, *args)
|
209
|
+
end
|
210
|
+
|
211
|
+
# pull
|
212
|
+
|
213
|
+
def pull_opts(options = nil)
|
214
|
+
GitOpts.new
|
215
|
+
.allow(:all, long: '--all')
|
216
|
+
.allow(:tags, short: '-t', long: '--tags')
|
217
|
+
.from(@options)
|
218
|
+
.from(options)
|
219
|
+
end
|
220
|
+
|
221
|
+
def pull(*args, git_options: nil, **options)
|
222
|
+
pull_git_options = git_opts(git_options)
|
223
|
+
pull_options = pull_opts(options)
|
224
|
+
|
225
|
+
exec(*pull_git_options, 'pull', *pull_options, *args)
|
226
|
+
end
|
227
|
+
|
228
|
+
# push
|
229
|
+
|
230
|
+
def push_opts(options = nil)
|
231
|
+
GitOpts.new
|
232
|
+
.allow(:all, long: '--all')
|
233
|
+
.allow(:mirror, long: '--mirror')
|
234
|
+
.allow(:tags, long: '--tags')
|
235
|
+
.from(@options)
|
236
|
+
.from(options)
|
237
|
+
end
|
238
|
+
|
239
|
+
def push(*args, git_options: nil, **options)
|
240
|
+
push_git_options = git_opts(git_options)
|
241
|
+
push_options = push_opts(options)
|
242
|
+
|
243
|
+
exec(*push_git_options, 'push', *push_options, *args)
|
244
|
+
end
|
245
|
+
|
246
|
+
# remote
|
247
|
+
|
248
|
+
def remote_opts(options = nil)
|
249
|
+
GitOpts.new
|
250
|
+
.allow(:verbose, short: '-v')
|
251
|
+
.from(@options)
|
252
|
+
.from(options)
|
253
|
+
end
|
254
|
+
|
255
|
+
def remote(*args, git_options: nil, **options)
|
256
|
+
remote_git_options = git_opts(git_options)
|
257
|
+
remote_options = remote_opts(options)
|
258
|
+
|
259
|
+
exec(*remote_git_options, 'remote', *remote_options, *args)
|
260
|
+
end
|
261
|
+
|
262
|
+
def remotes(git_options: nil)
|
263
|
+
Git::RemoteRefs.parse(remote(git_options: git_options, verbose: true))
|
264
|
+
end
|
265
|
+
|
266
|
+
# git_bin
|
267
|
+
|
268
|
+
DEFAULT_GIT_BIN = 'git'
|
269
|
+
|
270
|
+
class << self
|
271
|
+
attr_writer :git_bin
|
272
|
+
|
273
|
+
def git_bin
|
274
|
+
@git_bin ||= DEFAULT_GIT_BIN
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
# rubocop:enable Metrics/ClassLength, Metrics/MethodLength, Naming/PredicateName
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitw
|
4
|
+
# git options
|
5
|
+
# allow to define available options
|
6
|
+
# and to create standard args for execution
|
7
|
+
class GitOpts
|
8
|
+
def initialize
|
9
|
+
@allowed = []
|
10
|
+
@allowed_index = {}
|
11
|
+
|
12
|
+
@opts = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def allow(label, **kwargs)
|
16
|
+
allowed_opt = GitAllowedOpt.new(label, **kwargs)
|
17
|
+
return unless allowed_opt
|
18
|
+
|
19
|
+
@allowed << allowed_opt
|
20
|
+
allowed_opt.each_label do |allowed_opt_label|
|
21
|
+
@allowed_index[allowed_opt_label] = allowed_opt
|
22
|
+
end
|
23
|
+
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def opts
|
28
|
+
@opts.map do |label, arg|
|
29
|
+
linked_allowed_opt = @allowed_index[label]
|
30
|
+
next unless linked_allowed_opt
|
31
|
+
|
32
|
+
linked_allowed_opt.build_opt(arg)
|
33
|
+
end.compact
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_a
|
37
|
+
opts.flatten
|
38
|
+
end
|
39
|
+
|
40
|
+
def add(label, arg = nil)
|
41
|
+
@opts << [label, arg]
|
42
|
+
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def from_a(options)
|
47
|
+
options.each do |option|
|
48
|
+
add(option)
|
49
|
+
end
|
50
|
+
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
def from_h(options)
|
55
|
+
options.each do |k, v|
|
56
|
+
next if v == false
|
57
|
+
|
58
|
+
add(k, v)
|
59
|
+
end
|
60
|
+
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
def from(options)
|
65
|
+
case options
|
66
|
+
when Hash then from_h(options)
|
67
|
+
when Array then from_a(options)
|
68
|
+
else
|
69
|
+
self
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# git allowed options
|
75
|
+
# to defined single allowed options
|
76
|
+
# to be included in git options
|
77
|
+
class GitAllowedOpt
|
78
|
+
attr_reader :label, :short, :long, :with_arg, :multiple
|
79
|
+
|
80
|
+
def initialize(label, short: nil, long: nil, with_arg: false, multiple: false)
|
81
|
+
@label = label.to_s.to_sym
|
82
|
+
@short = short
|
83
|
+
@long = long
|
84
|
+
@with_arg = with_arg
|
85
|
+
@multiple = multiple
|
86
|
+
end
|
87
|
+
|
88
|
+
def each_label(&block)
|
89
|
+
[label, label.to_s, short, long].compact.each(&block)
|
90
|
+
end
|
91
|
+
|
92
|
+
def build_opt(arg = nil)
|
93
|
+
return if with_arg && arg.nil?
|
94
|
+
|
95
|
+
opt = []
|
96
|
+
opt << (long || short)
|
97
|
+
opt << arg if with_arg
|
98
|
+
opt.compact
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# frozen_string_literal: true
|
data/lib/gitw/version.rb
ADDED
data/lib/gitw.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'gitw/version'
|
4
|
+
require_relative 'gitw/repository'
|
5
|
+
require_relative 'gitw/git_exe'
|
6
|
+
|
7
|
+
# namespace for gitw library
|
8
|
+
# service entrypoint for
|
9
|
+
# - init
|
10
|
+
# - clone
|
11
|
+
# - repository
|
12
|
+
module Gitw
|
13
|
+
def self.init(dir = '.', **options)
|
14
|
+
Gitw::Repository.init(dir, **options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.clone(from, to = nil, **options)
|
18
|
+
Gitw::Repository.clone(from, to, **options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.repository(directory, **options)
|
22
|
+
Gitw::Repository.at(directory, **options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.git_bin=(git_bin)
|
26
|
+
Gitw::GitExe.git_bin = git_bin
|
27
|
+
end
|
28
|
+
end
|
data/scripts/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'gitw'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start(__FILE__)
|
data/scripts/setup
ADDED
metadata
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gitw
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Thomas Tych
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-05-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bump
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.10.0
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.10.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: byebug
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '11.1'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 11.1.3
|
37
|
+
type: :development
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '11.1'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 11.1.3
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: minitest
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '5.18'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '5.18'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rake
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '13.0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '13.0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: reek
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '6.1'
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 6.1.4
|
85
|
+
type: :development
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '6.1'
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 6.1.4
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: rubocop
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '1.21'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '1.21'
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: rubocop-minitest
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: 0.29.0
|
116
|
+
type: :development
|
117
|
+
prerelease: false
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 0.29.0
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: rubocop-rake
|
125
|
+
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: 0.6.0
|
130
|
+
type: :development
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - "~>"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: 0.6.0
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: simplecov
|
139
|
+
requirement: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: 0.22.0
|
144
|
+
type: :development
|
145
|
+
prerelease: false
|
146
|
+
version_requirements: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - "~>"
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: 0.22.0
|
151
|
+
- !ruby/object:Gem::Dependency
|
152
|
+
name: yard-doctest
|
153
|
+
requirement: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - "~>"
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: 0.1.17
|
158
|
+
type: :development
|
159
|
+
prerelease: false
|
160
|
+
version_requirements: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - "~>"
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: 0.1.17
|
165
|
+
- !ruby/object:Gem::Dependency
|
166
|
+
name: yardstick
|
167
|
+
requirement: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - "~>"
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: 0.9.9
|
172
|
+
type: :development
|
173
|
+
prerelease: false
|
174
|
+
version_requirements: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - "~>"
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: 0.9.9
|
179
|
+
description: git command wrabper
|
180
|
+
email:
|
181
|
+
- thomas.tych@gmail.com
|
182
|
+
executables: []
|
183
|
+
extensions: []
|
184
|
+
extra_rdoc_files: []
|
185
|
+
files:
|
186
|
+
- ".rubocop.yml"
|
187
|
+
- Gemfile
|
188
|
+
- README.md
|
189
|
+
- Rakefile
|
190
|
+
- lib/gitw.rb
|
191
|
+
- lib/gitw/exec.rb
|
192
|
+
- lib/gitw/git/remote_ref.rb
|
193
|
+
- lib/gitw/git/status.rb
|
194
|
+
- lib/gitw/git_error.rb
|
195
|
+
- lib/gitw/git_exe.rb
|
196
|
+
- lib/gitw/git_opts.rb
|
197
|
+
- lib/gitw/repository.rb
|
198
|
+
- lib/gitw/version.rb
|
199
|
+
- scripts/console
|
200
|
+
- scripts/setup
|
201
|
+
homepage: https://gitlab.com/ttych/gitw
|
202
|
+
licenses: []
|
203
|
+
metadata:
|
204
|
+
homepage_uri: https://gitlab.com/ttych/gitw
|
205
|
+
source_code_uri: https://gitlab.com/ttych/gitw
|
206
|
+
changelog_uri: https://gitlab.com/ttych/gitw/CHANGELOG.md
|
207
|
+
rubygems_mfa_required: 'true'
|
208
|
+
post_install_message:
|
209
|
+
rdoc_options: []
|
210
|
+
require_paths:
|
211
|
+
- lib
|
212
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
213
|
+
requirements:
|
214
|
+
- - ">="
|
215
|
+
- !ruby/object:Gem::Version
|
216
|
+
version: 2.6.0
|
217
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
218
|
+
requirements:
|
219
|
+
- - ">="
|
220
|
+
- !ruby/object:Gem::Version
|
221
|
+
version: '0'
|
222
|
+
requirements: []
|
223
|
+
rubygems_version: 3.4.12
|
224
|
+
signing_key:
|
225
|
+
specification_version: 4
|
226
|
+
summary: git command wrabper
|
227
|
+
test_files: []
|