rjgit 5.6.0.0 → 5.8.1.0

Sign up to get free protection for your applications and to get access to all the features.
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