git_wrapper 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +4 -0
  3. data/README.md +74 -0
  4. data/Rakefile +1 -0
  5. data/git_wrapper.gemspec +21 -0
  6. data/lib/git_wrapper/commands/add.rb +21 -0
  7. data/lib/git_wrapper/commands/branch.rb +73 -0
  8. data/lib/git_wrapper/commands/checkout.rb +21 -0
  9. data/lib/git_wrapper/commands/commit.rb +21 -0
  10. data/lib/git_wrapper/commands/config.rb +26 -0
  11. data/lib/git_wrapper/commands/diff.rb +27 -0
  12. data/lib/git_wrapper/commands/fetch.rb +21 -0
  13. data/lib/git_wrapper/commands/git.rb +44 -0
  14. data/lib/git_wrapper/commands/init.rb +16 -0
  15. data/lib/git_wrapper/commands/log.rb +82 -0
  16. data/lib/git_wrapper/commands/merge.rb +16 -0
  17. data/lib/git_wrapper/commands/pull.rb +21 -0
  18. data/lib/git_wrapper/commands/push.rb +27 -0
  19. data/lib/git_wrapper/commands/remote.rb +49 -0
  20. data/lib/git_wrapper/commands/remove.rb +16 -0
  21. data/lib/git_wrapper/commands/reset.rb +36 -0
  22. data/lib/git_wrapper/commands/revert.rb +23 -0
  23. data/lib/git_wrapper/commands/shell.rb +67 -0
  24. data/lib/git_wrapper/commands/show.rb +40 -0
  25. data/lib/git_wrapper/commands/status.rb +17 -0
  26. data/lib/git_wrapper/commands/tag.rb +54 -0
  27. data/lib/git_wrapper/repository.rb +208 -0
  28. data/lib/git_wrapper/results/diff_name_status.rb +28 -0
  29. data/lib/git_wrapper/results/file_status.rb +21 -0
  30. data/lib/git_wrapper/results/log_info.rb +23 -0
  31. data/lib/git_wrapper/results/status_porcelain.rb +40 -0
  32. data/lib/git_wrapper/version.rb +3 -0
  33. data/lib/git_wrapper.rb +45 -0
  34. data/spec/repository_spec.rb +886 -0
  35. data/spec/spec_helper.rb +10 -0
  36. data/spec/status_porcelain_parser_spec.rb +78 -0
  37. data/spec/support/helpers/file_helper.rb +37 -0
  38. data/spec/support/matchers/git_status_matchers.rb +40 -0
  39. metadata +105 -0
@@ -0,0 +1,67 @@
1
+ module GitWrapper
2
+ module Commands
3
+
4
+ module Shell
5
+
6
+ def self.execute(command, options={})
7
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
8
+ jruby_execute(command, options)
9
+ else
10
+ ruby_execute(command, options)
11
+ end
12
+ end
13
+
14
+ def self.ruby_execute(command, options={})
15
+ location_folder = options[:chdir] || '.'
16
+ result = nil
17
+
18
+ Open3.popen3(command, :chdir => location_folder) do |stdin, stdout, stderr, wait_thr|
19
+ output = stdout.readlines.join
20
+ error = stderr.readlines.join
21
+ status = wait_thr.value
22
+
23
+ if block_given?
24
+ result = status
25
+ yield(output, error, wait_thr.pid)
26
+ else
27
+ result = [output, error, status]
28
+ end
29
+ end
30
+
31
+ return result
32
+ end
33
+
34
+ def self.jruby_execute(command, options={})
35
+ location_folder = options[:chdir] || '.'
36
+
37
+ prev_stdout = $stdout
38
+ prev_stderr = $stderr
39
+
40
+ $stdout = StringIO.new
41
+ $stderr = StringIO.new
42
+
43
+ begin
44
+ Dir.chdir location_folder do
45
+ system(command)
46
+ end
47
+ status = $?
48
+ $stdout.rewind
49
+ $stderr.rewind
50
+ if block_given?
51
+ yield($stdout.readlines.join.force_encoding('UTF-8'), $stderr.readlines.join.force_encoding('UTF-8'), status.pid)
52
+ result = status
53
+ else
54
+ result = $stdout.readlines.join.force_encoding('UTF-8'), $stderr.readlines.join.force_encoding('UTF-8'), status
55
+ end
56
+ ensure
57
+ $stdout = prev_stdout
58
+ $stderr = prev_stderr
59
+ end
60
+
61
+ return result
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,40 @@
1
+ module GitWrapper
2
+ module Commands
3
+ class Show < Git
4
+
5
+ def file(file_name)
6
+ @file = to_relative_path(file_name)
7
+ self
8
+ end
9
+
10
+ def commit(commit)
11
+ @version = "#{commit}:"
12
+ self
13
+ end
14
+
15
+ def base
16
+ @version = ':1:'
17
+ self
18
+ end
19
+
20
+ def mine
21
+ @version = ':2:'
22
+ self
23
+ end
24
+
25
+ def theirs
26
+ @version = ':3:'
27
+ self
28
+ end
29
+
30
+ def command
31
+ "show #{@version ? @version : 'HEAD:'}\"#{@file}\""
32
+ end
33
+
34
+ def result
35
+ output
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,17 @@
1
+ module GitWrapper
2
+ module Commands
3
+ class Status < Git
4
+
5
+ def command
6
+ 'status --porcelain'
7
+ end
8
+
9
+ def result
10
+ output.split(/\n/).map do |line|
11
+ Results::StatusPorcelain.parse(line)
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ module GitWrapper
2
+ module Commands
3
+ class Tag < Git
4
+
5
+ def create(name)
6
+ @mode = :create
7
+ @name = name
8
+ self
9
+ end
10
+
11
+ def from(commit)
12
+ @commit = commit
13
+ self
14
+ end
15
+
16
+ def remove(name)
17
+ @mode = :remove
18
+ @name = name
19
+ self
20
+ end
21
+
22
+ def list
23
+ @mode = :list
24
+ self
25
+ end
26
+
27
+ def command
28
+ command = 'tag '
29
+
30
+ if @mode == :create
31
+ command += "#{@name} #{@commit.nil? ? '' : @commit}"
32
+ elsif @mode == :remove
33
+ command += "-d #{@name}"
34
+ elsif @mode == :list
35
+ #Nothing to add
36
+ else
37
+ raise 'Unespecified tag mode'
38
+ end
39
+
40
+ command
41
+ end
42
+
43
+ def result
44
+ return result_list if @mode == :list
45
+ super
46
+ end
47
+
48
+ def result_list
49
+ output.split("\n")
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,208 @@
1
+ module GitWrapper
2
+ class Repository
3
+ attr_reader :location
4
+ attr_reader :log_output
5
+ attr_reader :log_error
6
+
7
+ def initialize(location)
8
+ @location = location
9
+ @log_output = []
10
+ @log_error = []
11
+ end
12
+
13
+ def init
14
+ FileUtils.mkpath(@location) unless Dir.exist?(@location)
15
+ execute(Commands::Init.new(@location))
16
+ end
17
+
18
+ def init_bare
19
+ FileUtils.mkpath(@location) unless Dir.exist?(@location)
20
+ execute(Commands::Init.new(@location).bare)
21
+ end
22
+
23
+ def initialized?
24
+ Dir.exist?("#{@location}/.git") || bare?
25
+ end
26
+
27
+ def bare?
28
+ Dir.exist?("#{@location}/hooks") &&
29
+ Dir.exist?("#{@location}/info") &&
30
+ Dir.exist?("#{@location}/objects") &&
31
+ Dir.exist?("#{@location}/refs")
32
+ end
33
+
34
+ def status
35
+ execute(Commands::Status.new(@location))
36
+ end
37
+
38
+ def add(file_name)
39
+ execute(Commands::Add.new(@location).file(file_name))
40
+ end
41
+
42
+ def add_all
43
+ execute(Commands::Add.new(@location).all)
44
+ end
45
+
46
+ def commit(message, options={})
47
+ command = Commands::Commit.new(@location).message(message)
48
+ command.author(options[:author_name], options[:author_email]) if options[:author_name] && options[:author_email]
49
+ execute(command)
50
+ end
51
+
52
+ def remove(file_name)
53
+ execute(Commands::Remove.new(@location).file(file_name))
54
+ end
55
+
56
+ def remotes
57
+ execute(Commands::Remote.new(@location).list)
58
+ end
59
+
60
+ def add_remote(name, url)
61
+ execute(Commands::Remote.new(@location).name(name).add(url))
62
+ end
63
+
64
+ def remove_remote(name)
65
+ execute(Commands::Remote.new(@location).name(name).remove)
66
+ end
67
+
68
+ def pull(remote='origin', branch='master')
69
+ execute(Commands::Pull.new(@location).remote(remote).branch(branch))
70
+ end
71
+
72
+ def push(remote='origin', branch='master')
73
+ execute(Commands::Push.new(@location).remote(remote).branch(branch))
74
+ end
75
+
76
+ def push_tags(remote='origin')
77
+ execute(Commands::Push.new(@location).remote(remote).tags)
78
+ end
79
+
80
+ def show(file_name, commit=nil)
81
+ command = Commands::Show.new(@location).file(file_name)
82
+ command.commit(commit) unless commit.nil?
83
+ execute(command)
84
+ end
85
+
86
+ def show_base(file_name)
87
+ execute(Commands::Show.new(@location).file(file_name).base)
88
+ end
89
+
90
+ def show_mine(file_name)
91
+ execute(Commands::Show.new(@location).file(file_name).mine)
92
+ end
93
+
94
+ def show_theirs(file_name)
95
+ execute(Commands::Show.new(@location).file(file_name).theirs)
96
+ end
97
+
98
+ def log(options={})
99
+ if options[:file_name]
100
+ execute(Commands::Log.new(@location).file(options[:file_name]))
101
+ elsif options[:commit]
102
+ execute(Commands::Log.new(@location).commit(options[:commit]))
103
+ else
104
+ execute(Commands::Log.new(@location))
105
+ end
106
+ end
107
+
108
+ def branches
109
+ execute(Commands::Branch.new(@location).list)
110
+ end
111
+
112
+ def current_branch
113
+ execute(Commands::Branch.new(@location).current)
114
+ end
115
+
116
+ def branch(name, commit=nil)
117
+ if commit.nil?
118
+ execute(Commands::Branch.new(@location).create(name))
119
+ else
120
+ execute(Commands::Branch.new(@location).create(name).from(commit))
121
+ end
122
+ end
123
+
124
+ def remove_branch(name, remote=nil)
125
+ if remote.nil?
126
+ execute(Commands::Branch.new(@location).remove(name))
127
+ else
128
+ execute(Commands::Branch.new(@location).remove(name).remote(remote))
129
+ end
130
+ end
131
+
132
+ def checkout(commit, new_branch=nil)
133
+ if commit.nil?
134
+ execute(Commands::Checkout.new(@location).commit(commit))
135
+ else
136
+ execute(Commands::Checkout.new(@location).commit(commit).into(new_branch))
137
+ end
138
+ end
139
+
140
+ def tags
141
+ execute(Commands::Tag.new(@location).list)
142
+ end
143
+
144
+ def tag(name, commit=nil)
145
+ if commit.nil?
146
+ execute(Commands::Tag.new(@location).create(name))
147
+ else
148
+ execute(Commands::Tag.new(@location).create(name).from(commit))
149
+ end
150
+ end
151
+
152
+ def remove_tag(name)
153
+ execute(Commands::Tag.new(@location).remove(name))
154
+ end
155
+
156
+ def merge(commit)
157
+ execute(Commands::Merge.new(@location).commit(commit))
158
+ end
159
+
160
+ def fetch(remote=nil)
161
+ if remote.nil?
162
+ execute(Commands::Fetch.new(@location).all)
163
+ else
164
+ execute(Commands::Fetch.new(@location).remote(remote))
165
+ end
166
+ end
167
+
168
+ def diff(commit)
169
+ execute(Commands::Diff.new(@location).with(commit))
170
+ end
171
+
172
+ def diff_reverse(commit)
173
+ execute(Commands::Diff.new(@location).with(commit).reverse)
174
+ end
175
+
176
+ def revert(commit)
177
+ if log(:commit => commit).merge?
178
+ execute(Commands::Revert.new(@location).merge(commit))
179
+ else
180
+ execute(Commands::Revert.new(@location).commit(commit))
181
+ end
182
+ end
183
+
184
+ def reset(options={})
185
+ command = Commands::Reset.new(@location)
186
+ command.commit(options[:commit]) if options[:commit]
187
+ command.send(options[:mode]) if options[:mode]
188
+ execute(command)
189
+ end
190
+
191
+ def config(key=nil, value=nil)
192
+ command = Commands::Config.new(@location)
193
+ command.key(key) if key
194
+ command.value(value) if value
195
+ execute(command)
196
+ end
197
+
198
+ private
199
+
200
+ def execute(command)
201
+ result = command.execute
202
+ @log_output << command.output
203
+ @log_error << command.error
204
+ result
205
+ end
206
+
207
+ end
208
+ end
@@ -0,0 +1,28 @@
1
+ module GitWrapper
2
+ module Results
3
+ class DiffNameStatus
4
+ attr_reader :file_name
5
+ attr_reader :status
6
+
7
+ def initialize(file_name, status)
8
+ @file_name = file_name
9
+ @status = status
10
+ end
11
+
12
+ def self.parse(text)
13
+ DiffNameStatus.new parse_file_name(text), parse_status(text)
14
+ end
15
+
16
+ private
17
+
18
+ def self.parse_file_name(text)
19
+ text[1..text.length].strip
20
+ end
21
+
22
+ def self.parse_status(text)
23
+ FileStatus.value_of text[0]
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ module GitWrapper
2
+ module Results
3
+ module FileStatus
4
+ STATUSES = {
5
+ 'A' => :new_file,
6
+ 'M' => :modified,
7
+ 'D' => :deleted,
8
+ 'R' => :renamed,
9
+ 'U' => :merge_conflict,
10
+ 'C' => :copied,
11
+ 'T' => :type_changed,
12
+ 'X' => :unknown
13
+ }
14
+
15
+ def self.value_of(char)
16
+ return :untracked unless STATUSES.key?(char)
17
+ STATUSES[char]
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module GitWrapper
2
+ module Results
3
+ class LogInfo
4
+ def initialize(attributes)
5
+ attributes.each do |name, value|
6
+ define_singleton_method name, lambda { value }
7
+ end
8
+ end
9
+
10
+ def parents
11
+ parent_hashes.split
12
+ end
13
+
14
+ def abbreviated_parents
15
+ abbreviated_parent_hashes.split
16
+ end
17
+
18
+ def merge?
19
+ parents.length == 2
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ module GitWrapper
2
+ module Results
3
+ class StatusPorcelain
4
+ attr_reader :file_name
5
+ attr_reader :original_file_name
6
+ attr_reader :status
7
+ attr_reader :staged_for_commit
8
+
9
+ def initialize(file_name, original_file_name, status, staged_for_commit)
10
+ @file_name = file_name
11
+ @original_file_name = original_file_name
12
+ @status = status
13
+ @staged_for_commit = staged_for_commit
14
+ end
15
+
16
+ def self.parse(text)
17
+ StatusPorcelain.new parse_file_name(text), parse_original_file_name(text), parse_status(text), parse_staged_for_commit(text)
18
+ end
19
+
20
+ private
21
+
22
+ def self.parse_file_name(text)
23
+ text[3..text.length].gsub("\"", "").split(' -> ').last
24
+ end
25
+
26
+ def self.parse_original_file_name(text)
27
+ text[3..text.length].gsub("\"", "").split(' -> ').first
28
+ end
29
+
30
+ def self.parse_status(text)
31
+ FileStatus.value_of text[0..2].strip[0]
32
+ end
33
+
34
+ def self.parse_staged_for_commit(text)
35
+ text[1..2].strip.empty?
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module GitWrapper
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,45 @@
1
+ require 'logger'
2
+ require 'nokogiri'
3
+
4
+ require 'git_wrapper/version'
5
+
6
+ require 'git_wrapper/repository'
7
+
8
+ require 'git_wrapper/commands/shell'
9
+ require 'git_wrapper/commands/git'
10
+ require 'git_wrapper/commands/init'
11
+ require 'git_wrapper/commands/status'
12
+ require 'git_wrapper/commands/add'
13
+ require 'git_wrapper/commands/commit'
14
+ require 'git_wrapper/commands/remove'
15
+ require 'git_wrapper/commands/remote'
16
+ require 'git_wrapper/commands/pull'
17
+ require 'git_wrapper/commands/push'
18
+ require 'git_wrapper/commands/show'
19
+ require 'git_wrapper/commands/log'
20
+ require 'git_wrapper/commands/branch'
21
+ require 'git_wrapper/commands/checkout'
22
+ require 'git_wrapper/commands/tag'
23
+ require 'git_wrapper/commands/merge'
24
+ require 'git_wrapper/commands/fetch'
25
+ require 'git_wrapper/commands/diff'
26
+ require 'git_wrapper/commands/revert'
27
+ require 'git_wrapper/commands/reset'
28
+ require 'git_wrapper/commands/config'
29
+
30
+ require 'git_wrapper/results/file_status'
31
+ require 'git_wrapper/results/status_porcelain'
32
+ require 'git_wrapper/results/log_info'
33
+ require 'git_wrapper/results/diff_name_status'
34
+
35
+ module GitWrapper
36
+
37
+ def self.logger
38
+ @@logger ||= Logger.new($stdout)
39
+ end
40
+
41
+ def self.logger=(logger)
42
+ @@logger = logger
43
+ end
44
+
45
+ end