rjgit 5.6.0.0 → 5.8.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c590ad61a1ab2ef9e2a778f49722cf46886d390185a02aa6ca1ac8ef0b0e8073
4
- data.tar.gz: 2c13389fc678529de6623891ff123f6fe05effc86b147e21d488869bcfdb2741
3
+ metadata.gz: 2022eac50d1c23127bf8971f5b8b60e931eb643ea0a181956de3743418c62a00
4
+ data.tar.gz: 4c7ad80622c9889ab848c15e7d1fbcce99f41f08f4900620bf65d805f2da1ea6
5
5
  SHA512:
6
- metadata.gz: af2a8f79cf5600e81a6df902d10d4fa9d51ce2e52b99d012ca9c978e36611d332f6647a5c267e225e5e5626841fd28985efef97b171f47f293d3da2866ab592b
7
- data.tar.gz: acab43332a63d482908b9c52b835cfd9ee364880af1558c53829b81ef86a71a984b6d37413a36156331d47a7d21d4c4adc4cc5fd2b01a27b31c22c47d9f2c445
6
+ metadata.gz: e4da6ac22532cb16873e6d45246d7290695bc456abf73afd5eae8dced1141a14460fad41797927612585237f9e6fe7f5bcc0695dacfbe3fc9249e1134481a433
7
+ data.tar.gz: bd28dc840e9e7c2676ad4bb4aa6c7f9f16a5948d34fe8ecd5bb0930881cf5d0915d19ac62f969e1f06fd683fe3ad36e3b2d4365177a7f4dfe0ad88703af4b844
data/Gemfile CHANGED
@@ -1,12 +1,12 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem "mime-types", "~> 2.6.2"
4
- gem "rake", "~> 10.4.2"
3
+ gem 'mime-types', '~> 2.6.2'
4
+ gem 'rake', '>= 12.3.3'
5
5
 
6
- gem 'coveralls', require: false
6
+ gem 'coveralls', '~> 0.8.23', require: false
7
7
 
8
8
  group :test do
9
- gem "rspec", "~> 3.4.0"
10
- gem "rspec-collection_matchers", "~> 1.1.2"
11
- gem "simplecov"
9
+ gem 'rspec', '~> 3.4.0'
10
+ gem 'rspec-collection_matchers', '~> 1.1.2'
11
+ gem 'simplecov'
12
12
  end
data/README.md CHANGED
@@ -75,6 +75,13 @@ repo.find('959329025f67539fb82e76b02782322fad032821')
75
75
  repo.find('959329025f67539fb82e76b02782322fad032821', :commit) # Find a specific :commit, :blob, :tree, or :tag
76
76
  ```
77
77
 
78
+ ### Logs
79
+
80
+ ```ruby
81
+ repo.git.log # Returns an Array of Commits constituting the log for the default branch
82
+ repo.git.log("follow-rename.txt", "HEAD", follow: true, list_renames: true) # Log for a specific path, tracking the pathname over renames. Returns an Array of TrackingCommits, which store the tracked filename: [#<RJGit::TrackingCommit:0x773014d3 @tracked_pathname="follow-rename.txt" ...>]
83
+ ```
84
+
78
85
  ### Getting diffs
79
86
  ```ruby
80
87
  sha1 = repo.head.id
@@ -2,6 +2,7 @@ module RJGit
2
2
 
3
3
  # PersonIdent in JGit
4
4
  import 'org.eclipse.jgit.lib.PersonIdent'
5
+ import 'java.util.TimeZone'
5
6
 
6
7
  class Actor
7
8
 
@@ -17,10 +18,11 @@ module RJGit
17
18
  return self.new(name, email)
18
19
  end
19
20
 
20
- def initialize(name, email)
21
+ def initialize(name, email, time = nil)
21
22
  @name = name
22
23
  @email = email
23
- @person_ident = PersonIdent.new(name, email)
24
+ @time = time
25
+ @person_ident = @time ? PersonIdent.new(name, email, time.to_java, TimeZone.getTimeZone(time.zone)) : PersonIdent.new(name, email)
24
26
  end
25
27
 
26
28
  # Create an Actor from a string.
@@ -43,7 +45,8 @@ module RJGit
43
45
  # time - The Time the commit was authored or committed.
44
46
  #
45
47
  # Returns a String.
46
- def output(time)
48
+ def output(time = nil)
49
+ time = time || self.time
47
50
  offset = time.utc_offset / 60
48
51
  "%s <%s> %d %+.2d%.2d" % [
49
52
  @name,
@@ -52,6 +55,10 @@ module RJGit
52
55
  offset / 60,
53
56
  offset.abs % 60]
54
57
  end
58
+
59
+ def time
60
+ Time.at(@person_ident.getWhen.getTime/1000)
61
+ end
55
62
 
56
63
  end
57
64
 
@@ -4,7 +4,7 @@ module RJGit
4
4
  import 'org.eclipse.jgit.revwalk.RevCommit'
5
5
  import 'org.eclipse.jgit.diff.DiffFormatter'
6
6
  import 'org.eclipse.jgit.util.io.DisabledOutputStream'
7
-
7
+
8
8
  class Commit
9
9
 
10
10
  attr_reader :id, :parents, :actor, :committer, :authored_date, :committed_date
@@ -100,12 +100,12 @@ module RJGit
100
100
  Commit.new(repository, RevWalk.new(repository).parseCommit(new_commit))
101
101
  end
102
102
 
103
- def self.find_head(repository)
103
+ def self.find_head(repository, ref = Constants::HEAD)
104
104
  repository = RJGit.repository_type(repository)
105
105
  return nil if repository.nil?
106
106
  begin
107
107
  walk = RevWalk.new(repository)
108
- objhead = repository.resolve(Constants::HEAD)
108
+ objhead = repository.resolve(ref)
109
109
  return Commit.new(repository, walk.parseCommit(objhead))
110
110
  rescue java.lang.NullPointerException => e
111
111
  return nil
@@ -128,4 +128,13 @@ module RJGit
128
128
  end
129
129
 
130
130
  end
131
+
132
+ class TrackingCommit < Commit
133
+ attr_reader :tracked_pathname # This commit is part of a log for a single pathname. The tracked_pathname attribute tracks the pathname over renames.
134
+
135
+ def initialize(repository, commit, tracked_pathname = nil)
136
+ super(repository, commit)
137
+ @tracked_pathname = tracked_pathname
138
+ end
139
+ end
131
140
  end
data/lib/git.rb CHANGED
@@ -15,6 +15,10 @@ module RJGit
15
15
  import 'org.eclipse.jgit.api.TransportConfigCallback'
16
16
  import 'org.eclipse.jgit.transport.JschConfigSessionFactory'
17
17
  import 'org.eclipse.jgit.transport.SshTransport'
18
+ import 'org.eclipse.jgit.revwalk.FollowFilter'
19
+ import 'org.eclipse.jgit.revwalk.TreeRevFilter'
20
+
21
+ class PatchApplyException < StandardError; end
18
22
 
19
23
  class RubyGit
20
24
 
@@ -47,67 +51,58 @@ module RJGit
47
51
  return [] unless ref
48
52
  jcommits = Array.new
49
53
 
54
+ logs = @jgit.log
55
+ logs.add(ref)
56
+
50
57
  if path && options[:follow]
51
- current_path = path
52
- start = nil
53
- loop do
54
- logs = @jgit.log.add(ref).addPath(current_path).call
55
- logs.each do |jcommit|
56
- next if jcommits.include?(jcommit)
57
- jcommits << jcommit
58
- start = jcommit
59
- end
60
- current_path = follow_renames(start, current_path) if start
61
- break if current_path.nil?
62
- end
58
+ cfg = Configuration.new(nil)
59
+ cfg.add_setting('renames', true, 'diffs', nil)
60
+ follow = FollowFilter.create(path, cfg.jconfig.get(org.eclipse.jgit.diff.DiffConfig::KEY))
61
+ logs.set_rev_filter(TreeRevFilter.new(RevWalk.new(jrepo), follow))
62
+ elsif path
63
+ logs.addPath(path)
64
+ end
63
65
 
64
- else
65
- logs = @jgit.log
66
- logs.add(ref)
67
- logs.addPath(path) if path
68
- logs.setMaxCount(options[:max_count]) if options[:max_count]
69
- logs.setSkip(options[:skip]) if options[:skip]
70
-
71
- if (options[:since] && options[:until])
72
- revwalk = RevWalk.new(jrepo)
73
- since_commit = revwalk.parseCommit(jrepo.resolve(options[:since]))
74
- until_commit = revwalk.parseCommit(jrepo.resolve(options[:until]))
75
- logs.addRange(since_commit, until_commit)
76
- end
77
- if options[:not]
78
- revwalk = RevWalk.new(jrepo)
79
- options[:not].each do |ref|
80
- logs.not(revwalk.parseCommit(jrepo.resolve(ref)))
81
- end
82
- end
83
- jcommits = logs.call
66
+ logs.setMaxCount(options[:max_count]) if options[:max_count]
67
+ logs.setSkip(options[:skip]) if options[:skip]
68
+
69
+ if (options[:since] && options[:until])
70
+ revwalk = RevWalk.new(jrepo)
71
+ since_commit = revwalk.parseCommit(jrepo.resolve(options[:since]))
72
+ until_commit = revwalk.parseCommit(jrepo.resolve(options[:until]))
73
+ logs.addRange(since_commit, until_commit)
84
74
  end
85
75
 
86
- jcommits.map{ |jcommit| Commit.new(jrepo, jcommit) }
87
- end
76
+ if options[:not]
77
+ revwalk = RevWalk.new(jrepo)
78
+ options[:not].each do |ref|
79
+ logs.not(revwalk.parseCommit(jrepo.resolve(ref)))
80
+ end
81
+ end
88
82
 
89
- def follow_renames(jcommit, path)
90
- commits = @jgit.log.add(jcommit).call
91
- commits.each do |jcommit_prev|
92
- tree_start = jcommit.getTree
93
- tree_prev = jcommit_prev.getTree
94
- treewalk = TreeWalk.new(jrepo)
95
- #treewalk.setFilter(PathFilter.create(File.dirname(path)))
96
- treewalk.addTree(tree_prev)
97
- treewalk.addTree(tree_start)
98
- treewalk.setRecursive(true)
99
- rename_detector = RenameDetector.new(jrepo)
100
- rename_detector.addAll(DiffEntry.scan(treewalk))
101
- diff_entries = rename_detector.compute
102
- diff_entries.each do |entry|
103
- if ((entry.getChangeType == DiffEntry::ChangeType::RENAME || entry.getChangeType == DiffEntry::ChangeType::COPY) && entry.getNewPath.match(path))
104
- return entry.getOldPath
105
- end
83
+ if options[:follow] && options[:list_renames]
84
+ df = DiffFormatter.new(DisabledOutputStream::INSTANCE)
85
+ df.set_repository(jrepo)
86
+ df.set_context(0)
87
+ df.set_path_filter(follow)
88
+ df.set_detect_renames(true)
89
+ prev_commit = nil
90
+ pathname = path
91
+ end
92
+
93
+ commits = logs.call.map do |jcommit|
94
+ if path && options[:follow] && options[:list_renames]
95
+ entries = df.scan(jcommit, prev_commit).to_a
96
+ pathname = entries.empty? ? pathname : entries.last.get_old_path
97
+ prev_commit = jcommit
98
+ TrackingCommit.new(jrepo, jcommit, pathname)
99
+ else
100
+ Commit.new(jrepo, jcommit)
106
101
  end
107
102
  end
108
- return nil
109
- end
110
103
 
104
+ commits
105
+ end
111
106
 
112
107
  def branch_list
113
108
  branch = @jgit.branch_list
@@ -289,7 +284,11 @@ module RJGit
289
284
  end
290
285
 
291
286
  def apply(input_stream)
292
- apply_result = @jgit.apply.set_patch(input_stream).call
287
+ begin
288
+ apply_result = @jgit.apply.set_patch(input_stream).call
289
+ rescue Java::OrgEclipseJgitApiErrors::PatchApplyException
290
+ raise RJGit::PatchApplyException
291
+ end
293
292
  updated_files = apply_result.get_updated_files
294
293
  updated_files_parsed = []
295
294
  updated_files.each do |file|
@@ -1,5 +1,4 @@
1
1
  module RJGit
2
-
3
2
  begin
4
3
  require 'java'
5
4
  Dir["#{File.dirname(__FILE__)}/java/jars/*.jar"].each { |jar| require jar }
@@ -10,7 +9,7 @@ module RJGit
10
9
  def self.version
11
10
  VERSION
12
11
  end
13
-
12
+
14
13
  require 'uri'
15
14
  require 'stringio'
16
15
  # gem requires
@@ -19,37 +18,42 @@ module RJGit
19
18
  require "#{File.dirname(__FILE__)}/rjgit_helpers.rb"
20
19
  # require everything else
21
20
  begin
22
- Dir["#{File.dirname(__FILE__)}/*.rb"].each do |file|
21
+ Dir["#{File.dirname(__FILE__)}/*.rb"].each do |file|
23
22
  require file
24
23
  end
25
24
  end
26
-
25
+
27
26
  import 'org.eclipse.jgit.lib.ObjectId'
28
-
27
+
29
28
  module Porcelain
30
-
29
+
30
+ import 'java.io.IOException'
31
+ import 'org.eclipse.jgit.lib.Constants'
31
32
  import 'org.eclipse.jgit.api.AddCommand'
32
33
  import 'org.eclipse.jgit.api.CommitCommand'
33
34
  import 'org.eclipse.jgit.api.BlameCommand'
35
+ import 'org.eclipse.jgit.api.errors.RefNotFoundException'
34
36
  import 'org.eclipse.jgit.blame.BlameGenerator'
35
37
  import 'org.eclipse.jgit.blame.BlameResult'
38
+ import 'org.eclipse.jgit.errors.IncorrectObjectTypeException'
39
+ import 'org.eclipse.jgit.errors.InvalidPatternException'
40
+ import 'org.eclipse.jgit.errors.MissingObjectException'
36
41
  import 'org.eclipse.jgit.treewalk.CanonicalTreeParser'
37
42
  import 'org.eclipse.jgit.diff.DiffFormatter'
38
43
 
39
-
40
44
  # http://wiki.eclipse.org/JGit/User_Guide#Porcelain_API
41
45
  def self.add(repository, file_pattern)
42
46
  repository.add(file_pattern)
43
47
  end
44
-
48
+
45
49
  def self.commit(repository, message="")
46
50
  repository.commit(message)
47
51
  end
48
-
52
+
49
53
  def self.object_for_tag(repository, tag)
50
54
  repository.find(tag.object.name, RJGit.sym_for_type(tag.object_type))
51
55
  end
52
-
56
+
53
57
  # http://dev.eclipse.org/mhonarc/lists/jgit-dev/msg00558.html
54
58
  def self.cat_file(repository, blob)
55
59
  jrepo = RJGit.repository_type(repository)
@@ -65,7 +69,7 @@ module RJGit
65
69
  bytes = jrepo.open(jblob.id).get_bytes
66
70
  return bytes.to_a.pack('c*').force_encoding('UTF-8')
67
71
  end
68
-
72
+
69
73
  def self.ls_tree(repository, path=nil, treeish=Constants::HEAD, options={})
70
74
  options = {recursive: false, print: false, io: $stdout, path_filter: nil}.merge options
71
75
  jrepo = RJGit.repository_type(repository)
@@ -95,7 +99,7 @@ module RJGit
95
99
  treewalk.set_recursive(options[:recursive])
96
100
  treewalk.set_filter(PathFilter.create(options[:path_filter])) if options[:path_filter]
97
101
  entries = []
98
-
102
+
99
103
  while treewalk.next
100
104
  entry = {}
101
105
  mode = treewalk.get_file_mode(0)
@@ -107,8 +111,8 @@ module RJGit
107
111
  end
108
112
  options[:io].puts RJGit.stringify(entries) if options[:print]
109
113
  entries
110
- end
111
-
114
+ end
115
+
112
116
  def self.blame(repository, file_path, options={})
113
117
  options = {:print => false, :io => $stdout}.merge(options)
114
118
  jrepo = RJGit.repository_type(repository)
@@ -130,28 +134,22 @@ module RJGit
130
134
  options[:io].puts RJGit.stringify(blame) if options[:print]
131
135
  return blame
132
136
  end
133
-
137
+
134
138
  def self.diff(repository, options = {})
135
139
  options = {:namestatus => false, :patch => false}.merge(options)
136
140
  repo = RJGit.repository_type(repository)
137
141
  git = RubyGit.new(repo).jgit
138
142
  diff_command = git.diff
139
- if options[:old_rev]
143
+ [:old, :new].each do |which_rev|
144
+ if rev = options["#{which_rev}_rev".to_sym]
140
145
  reader = repo.new_object_reader
141
- old_tree = repo.resolve("#{options[:old_rev]}^{tree}")
142
- old_tree_iter = CanonicalTreeParser.new
143
- old_tree_iter.reset(reader, old_tree)
144
- diff_command.set_old_tree(old_tree_iter)
145
- end
146
- if options[:new_rev]
147
- reader = repo.new_object_reader unless reader
148
- new_tree = repo.resolve("#{options[:new_rev]}^{tree}")
149
- new_tree_iter = CanonicalTreeParser.new
150
- new_tree_iter.reset(reader, new_tree)
151
- diff_command.set_new_tree(new_tree_iter)
146
+ parser = CanonicalTreeParser.new
147
+ parser.reset(reader, repo.resolve("#{rev}^{tree}"))
148
+ diff_command.send("set_#{which_rev}_tree".to_sym, parser)
152
149
  end
150
+ end
153
151
  diff_command.set_path_filter(PathFilter.create(options[:file_path])) if options[:file_path]
154
- diff_command.set_show_name_and_status_only(true) if options[:namestatus]
152
+ diff_command.set_show_name_and_status_only(true) if options[:namestatus]
155
153
  diff_command.set_cached(true) if options[:cached]
156
154
  diff_entries = diff_command.call
157
155
  diff_entries = diff_entries.to_array.to_ary
@@ -169,34 +167,86 @@ module RJGit
169
167
  diff_entries = options[:patch] ? result : diff_entries.map {|entry| [entry]}
170
168
  RJGit.convert_diff_entries(diff_entries)
171
169
  end
172
-
170
+
171
+ def self.describe(repository, ref, options = {})
172
+ options = {:always => false, :long => false, :tags => false, :match => []}.merge(options)
173
+ repo = RJGit.repository_type(repository)
174
+ git = RubyGit.new(repo).jgit
175
+ command = git.describe.
176
+ set_always(options[:always]).
177
+ set_long(options[:long]).
178
+ set_tags(options[:tags])
179
+ begin
180
+ command = command.set_target(ref)
181
+ rescue IncorrectObjectTypeException, IOException, MissingObjectException, RefNotFoundException
182
+ return nil
183
+ end
184
+ options[:match].each do |match|
185
+ begin
186
+ command = command.set_match(match)
187
+ rescue InvalidPatternException
188
+ return nil
189
+ end
190
+ end
191
+ command.call
192
+ end
193
+
194
+ # options:
195
+ # * ref
196
+ # * path_filter
197
+ # * case_insensitive
198
+ def self.grep(repository, query, options={})
199
+ case_insensitive = options[:case_insensitive]
200
+ repo = RJGit.repository_type(repository)
201
+ walk = RevWalk.new(repo)
202
+ ls_tree_options = {:recursive => true, :path_filter => options[:path_filter]}
203
+
204
+ query = case query
205
+ when Regexp then query
206
+ when String then Regexp.new(Regexp.escape(query))
207
+ else raise "A #{query.class} was passed to #{self}.grep(). Only Regexps and Strings are supported!"
208
+ end
209
+
210
+ query = Regexp.new(query.source, query.options | Regexp::IGNORECASE) if case_insensitive
211
+
212
+ ls_tree(repo, nil, options.fetch(:ref, 'HEAD'), ls_tree_options).each_with_object({}) do |item, result|
213
+ blob = Blob.new(repo, item[:mode], item[:path], walk.lookup_blob(ObjectId.from_string(item[:id])))
214
+ next if blob.binary?
215
+
216
+ rows = blob.data.split("\n")
217
+ data = rows.grep(query)
218
+ next if data.empty?
219
+
220
+ result[blob.path] = data
221
+ end
222
+ end
173
223
  end
174
-
224
+
175
225
  module Plumbing
176
226
  import org.eclipse.jgit.lib.Constants
177
-
227
+
178
228
  class TreeBuilder
179
229
  import org.eclipse.jgit.lib.FileMode
180
230
  import org.eclipse.jgit.lib.TreeFormatter
181
-
182
-
231
+ import org.eclipse.jgit.patch.Patch
232
+
183
233
  attr_accessor :treemap
184
234
  attr_reader :log
185
-
235
+
186
236
  def initialize(repository)
187
237
  @jrepo = RJGit.repository_type(repository)
188
238
  @treemap = {}
189
239
  init_log
190
240
  end
191
-
241
+
192
242
  def object_inserter
193
243
  @object_inserter ||= @jrepo.newObjectInserter
194
244
  end
195
-
245
+
196
246
  def init_log
197
247
  @log = {:deleted => [], :added => [] }
198
248
  end
199
-
249
+
200
250
  def only_contains_deletions(hashmap)
201
251
  hashmap.each do |key, value|
202
252
  if value.is_a?(Hash)
@@ -207,7 +257,7 @@ module RJGit
207
257
  end
208
258
  true
209
259
  end
210
-
260
+
211
261
  def build_tree(start_tree, treemap = nil, flush = false)
212
262
  existing_trees = {}
213
263
  untouched_objects = {}
@@ -232,7 +282,7 @@ module RJGit
232
282
  end
233
283
  end
234
284
  end
235
-
285
+
236
286
  sorted_treemap = treemap.inject({}) {|h, (k,v)| v.is_a?(Hash) ? h["#{k}/"] = v : h[k] = v; h }.merge(untouched_objects).sort
237
287
  sorted_treemap.each do |object_name, data|
238
288
  case data
@@ -252,27 +302,27 @@ module RJGit
252
302
  end
253
303
  object_inserter.insert(formatter)
254
304
  end
255
-
305
+
256
306
  def write_blob(contents, flush = false)
257
307
  blobid = object_inserter.insert(Constants::OBJ_BLOB, contents.to_java_bytes)
258
308
  object_inserter.flush if flush
259
309
  blobid
260
310
  end
261
-
311
+
262
312
  end
263
-
313
+
264
314
  class Index
265
315
  import org.eclipse.jgit.lib.CommitBuilder
266
-
316
+
267
317
  attr_accessor :treemap, :current_tree
268
318
  attr_reader :jrepo
269
-
319
+
270
320
  def initialize(repository)
271
321
  @treemap = {}
272
322
  @jrepo = RJGit.repository_type(repository)
273
323
  @treebuilder = TreeBuilder.new(@jrepo)
274
324
  end
275
-
325
+
276
326
  def add(path, data)
277
327
  path = path[1..-1] if path[0] == '/'
278
328
  path = path.split('/')
@@ -289,24 +339,24 @@ module RJGit
289
339
  current[filename] = data
290
340
  @treemap
291
341
  end
292
-
342
+
293
343
  def delete(path)
294
344
  path = path[1..-1] if path[0] == '/'
295
345
  path = path.split('/')
296
346
  last = path.pop
297
-
347
+
298
348
  current = self.treemap
299
-
349
+
300
350
  path.each do |dir|
301
351
  current[dir] ||= {}
302
352
  node = current[dir]
303
353
  current = node
304
354
  end
305
-
355
+
306
356
  current[last] = false
307
357
  @treemap
308
358
  end
309
-
359
+
310
360
  def do_commit(message, author, parents, new_tree)
311
361
  commit_builder = CommitBuilder.new
312
362
  person = author.person_ident
@@ -323,14 +373,11 @@ module RJGit
323
373
  @treebuilder.object_inserter.flush
324
374
  result
325
375
  end
326
-
327
- def commit(message, author, parents = nil, ref = nil, force = false)
328
- ref = ref ? ref : "refs/heads/#{Constants::MASTER}"
329
- @current_tree = @current_tree ? RJGit.tree_type(@current_tree) : @jrepo.resolve("refs/heads/#{Constants::MASTER}^{tree}")
330
- @treebuilder.treemap = @treemap
331
- new_tree = @treebuilder.build_tree(@current_tree)
376
+
377
+ def commit(message, author, parents = nil, ref = "refs/heads/#{Constants::MASTER}", force = false)
378
+ new_tree = build_new_tree(@treemap, "#{ref}^{tree}")
332
379
  return false if @current_tree && new_tree.name == @current_tree.name
333
-
380
+
334
381
  parents = parents ? parents : @jrepo.resolve(ref+"^{commit}")
335
382
  new_head = do_commit(message, author, parents, new_tree)
336
383
 
@@ -341,21 +388,129 @@ module RJGit
341
388
  ru.setRefLogIdent(author.person_ident)
342
389
  ru.setRefLogMessage("commit: #{message}", false)
343
390
  res = ru.update.to_string
344
-
345
- # @treebuilder.object_inserter.release
391
+
346
392
  @current_tree = new_tree
347
393
  log = @treebuilder.log
348
394
  @treebuilder.init_log
349
395
  sha = ObjectId.to_string(new_head)
350
396
  return res, log, sha
351
397
  end
352
-
398
+
353
399
  def self.successful?(result)
354
400
  ["NEW", "FAST_FORWARD", "FORCED"].include?(result)
355
401
  end
356
402
 
403
+ private
404
+
405
+ def build_new_tree(treemap, ref)
406
+ @treebuilder.treemap = treemap
407
+ new_tree = @treebuilder.build_tree(@current_tree ? RJGit.tree_type(@current_tree) : @jrepo.resolve(ref))
408
+ end
409
+
357
410
  end
358
-
411
+
412
+ class ApplyPatchToIndex < RJGit::Plumbing::Index
413
+
414
+ import org.eclipse.jgit.patch.Patch
415
+ import org.eclipse.jgit.diff.DiffEntry
416
+
417
+ ADD = org.eclipse.jgit.diff.DiffEntry::ChangeType::ADD
418
+ COPY = org.eclipse.jgit.diff.DiffEntry::ChangeType::COPY
419
+ MODIFY = org.eclipse.jgit.diff.DiffEntry::ChangeType::MODIFY
420
+ DELETE = org.eclipse.jgit.diff.DiffEntry::ChangeType::DELETE
421
+ RENAME = org.eclipse.jgit.diff.DiffEntry::ChangeType::RENAME
422
+
423
+ # Take the result of RJGit::Porcelain.diff with options[:patch] = true and return a patch String
424
+ def self.diffs_to_patch(diffs)
425
+ diffs.inject(""){|result, diff| result << diff[:patch]}
426
+ end
427
+
428
+ def initialize(repository, patch, ref = Constants::HEAD)
429
+ super(repository)
430
+ @ref = ref
431
+ @patch = Patch.new
432
+ @patch.parse(ByteArrayInputStream.new(patch.to_java_bytes))
433
+ raise_patch_apply_error unless @patch.getErrors.isEmpty()
434
+ @current_tree = Commit.find_head(@jrepo, ref).tree
435
+ end
436
+
437
+ def commit(message, author, parents = nil, force = false)
438
+ super(message, author, parents, @ref, force)
439
+ end
440
+
441
+ def build_map
442
+ raise_patch_apply_error if @patch.getFiles.isEmpty()
443
+ @patch.getFiles.each do |file_header|
444
+ case file_header.getChangeType
445
+ when ADD
446
+ add(file_header.getNewPath, apply('', file_header))
447
+ when MODIFY
448
+ add(file_header.getOldPath, apply(getData(file_header.getOldPath), file_header))
449
+ when DELETE
450
+ delete(file_header.getOldPath)
451
+ when RENAME
452
+ delete(file_header.getOldPath)
453
+ add(file_header.getNewPath, getData(file_header.getOldPath))
454
+ when COPY
455
+ add(file_header.getNewPath, getData(file_header.getOldPath))
456
+ end
457
+ end
458
+ @treemap
459
+ end
460
+
461
+ # Build the new tree based on the patch, but don't commit it
462
+ # Return the String object id of the new tree, and an Array of affected paths
463
+ def new_tree
464
+ map = build_map
465
+ return ObjectId.to_string(build_new_tree(map, @ref)), map.keys
466
+ end
467
+
468
+ private
469
+
470
+ def raise_patch_apply_error
471
+ raise ::RJGit::PatchApplyException.new('Patch failed to apply')
472
+ end
473
+
474
+ def getData(path)
475
+ begin
476
+ (@current_tree / path).data
477
+ rescue NoMethodError
478
+ raise_patch_apply_error
479
+ end
480
+ end
481
+
482
+ def hunk_sanity_check(hunk, hunk_line, pos, newLines)
483
+ raise_patch_apply_error unless newLines[hunk.getNewStartLine - 1 + pos] == hunk_line[1..-1]
484
+ end
485
+
486
+ def apply(original, file_header)
487
+ newLines = original.lines
488
+ file_header.getHunks.each do |hunk|
489
+ length = hunk.getEndOffset - hunk.getStartOffset
490
+ buffer_text = hunk.getBuffer.to_s.slice(hunk.getStartOffset, length)
491
+ pos = 0
492
+ buffer_text.each_line do |hunk_line|
493
+ case hunk_line[0]
494
+ when ' '
495
+ hunk_sanity_check(hunk, hunk_line, pos, newLines)
496
+ pos += 1
497
+ when '-'
498
+ if hunk.getNewStartLine == 0
499
+ newLines = []
500
+ else
501
+ hunk_sanity_check(hunk, hunk_line, pos, newLines)
502
+ newLines.slice!(hunk.getNewStartLine - 1 + pos)
503
+ end
504
+ when '+'
505
+ newLines.insert(hunk.getNewStartLine - 1 + pos, hunk_line[1..-1])
506
+ pos += 1
507
+ end
508
+ end
509
+ end
510
+ newLines.join
511
+ end
512
+ end
513
+
359
514
  end
360
-
515
+
361
516
  end
@@ -1,3 +1,3 @@
1
1
  module RJGit
2
- VERSION = "5.6.0.0"
2
+ VERSION = "5.8.1.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rjgit
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.0.0
4
+ version: 5.8.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maarten Engelen
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2019-12-30 00:00:00.000000000 Z
15
+ date: 2020-08-14 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  requirement: !ruby/object:Gem::Requirement
@@ -49,7 +49,8 @@ files:
49
49
  - lib/java/jars/bcpkix-jdk15on-161.jar
50
50
  - lib/java/jars/bcprov-jdk15on-161.jar
51
51
  - lib/java/jars/jsch-0.1.54.jar
52
- - lib/java/jars/org.eclipse.jgit-5.6.0.201912101111-r.jar
52
+ - lib/java/jars/org.eclipse.jgit-5.8.1.202007141445-r.jar
53
+ - lib/java/jars/org.eclipse.jgit.ssh.jsch-5.8.0.202006091008-r.jar
53
54
  - lib/java/jars/slf4j-api-1.7.2.jar
54
55
  - lib/java/jars/slf4j-simple-1.7.12.jar
55
56
  - lib/repo.rb