gitlab-gollum-rugged_adapter 0.4.4

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 602fa2fbdbdba48ed81659c65373c3f89f73d245
4
+ data.tar.gz: 84d10ccbcc126577a331e8cf1c598da1f0716c95
5
+ SHA512:
6
+ metadata.gz: 4d75da96e99eba43a6ac0aa4835df66f9716f2df4afe1b89d246f0ab23493c7e08411d20cab75ed5d63f8e5663e968e51f661dec99c7cf92529064079505e5ec
7
+ data.tar.gz: b1686a416eaa3f0a609575042c1e5389d4b9bec438d0410e3cf31dc21accbb2dca0d1aeb3c5b7f99bd28c82c8044257667de04ff960a79ff7af94c9bafcf3832
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+ gem 'rake', '~> 10.4.2'
5
+ gem 'adapter_specs', git: 'https://github.com/gollum/adapter_specs.git'
6
+
7
+ group :test do
8
+ gem "simplecov"
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) Bart Kamphorst, Dawa Ometto
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the 'Software'), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,44 @@
1
+ [![Gem Version](https://badge.fury.io/rb/gollum-rugged_adapter.svg)](http://badge.fury.io/rb/gollum-rugged_adapter)
2
+ [![Build Status](https://travis-ci.org/gollum/rugged_adapter.svg?branch=master)](https://travis-ci.org/gollum/rugged_adapter)
3
+ [![Dependency Status](https://gemnasium.com/gollum/rugged_adapter.svg)](https://gemnasium.com/gollum/rugged_adapter)
4
+
5
+ ## DESCRIPTION
6
+
7
+ Adapter for [gollum](https://github.com/gollum/gollum) to use [Rugged](https://github.com/libgit2/rugged) (libgit2) at the backend. See the [gollum wiki](https://github.com/gollum/gollum/wiki/Git-adapters) for more information on adapters. Currently gollum uses grit as a backend by default, but since that is abandonware, the plan is to make this adapter the default in the future.
8
+
9
+ **Please note that this adapter is currently in beta. It passes the unit tests for gollum and [gollum-lib](https://github.com/gollum/gollum-lib), but it needs more comprehensive testing. Please [report any issues](https://github.com/gollum/rugged_adapter/issues) that you encounter.**
10
+
11
+ ## USAGE
12
+
13
+ Install the gem:
14
+
15
+ ```bash
16
+ gem install --pre gollum-rugged_adapter # --pre required for beta-releases
17
+ ```
18
+
19
+ Now run gollum as follows:
20
+
21
+ ```bash
22
+ gollum --adapter rugged
23
+ ```
24
+
25
+ ## CONTRIBUTING
26
+
27
+ 1. Start by cloning the repo [on GitHub](http://github.com/gollum/rugged_adapter).
28
+ 2. From inside the repo's directory, install the (development) dependencies with `bundle install`
29
+ 3. Create a thoughtfully named topic branch to contain your changes.
30
+ 4. Hack away.
31
+ 5. Make sure your changes pass the adapter's specs: `bundle exec rake`
32
+ 6. Make sure your changes pass gollum-lib's tests
33
+ * Clone [gollum-lib](https://github.com/gollum/gollum-lib) and add your local version of the rugged adapter to the gollum-lib `Gemfile`:
34
+
35
+ `gem "gollum-rugged_adapter", :path => '/path/to/rugged_adapter'`
36
+ * `bundle install`
37
+ * `bundle exec rake GIT_ADAPTER=rugged`
38
+ 1. If necessary, rebase your commits into logical chunks, without errors.
39
+ 1. Push the branch up to GitHub.
40
+ 1. Send a pull request to the gollum/rugged_adapter project.
41
+
42
+ ## RELEASING
43
+
44
+ This gem uses [Semantic Versioning](http://semver.org/).
data/Rakefile ADDED
@@ -0,0 +1,126 @@
1
+ require 'rubygems'
2
+
3
+ task :default => :rspec
4
+
5
+ require 'rspec/core/rake_task'
6
+
7
+ def name
8
+ "rugged_adapter"
9
+ end
10
+
11
+ def version
12
+ line = File.read("lib/rugged_adapter/version.rb")[/^\s*VERSION\s*=\s*.*/]
13
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
14
+ end
15
+
16
+ # assumes x.y.z all digit version
17
+ def next_version
18
+ # x.y.z
19
+ v = version.split '.'
20
+ # bump z
21
+ v[-1] = v[-1].to_i + 1
22
+ v.join '.'
23
+ end
24
+
25
+ def bump_version
26
+ old_file = File.read("lib/#{name}/version.rb")
27
+ old_version_line = old_file[/^\s*VERSION\s*=\s*.*/]
28
+ new_version = next_version
29
+ # replace first match of old version with new version
30
+ old_file.sub!(old_version_line, " VERSION = '#{new_version}'")
31
+
32
+ File.write("lib/#{name}/version.rb", old_file)
33
+
34
+ new_version
35
+ end
36
+
37
+ def date
38
+ Date.today.to_s
39
+ end
40
+
41
+ def gemspec
42
+ "#{name}.gemspec"
43
+ end
44
+
45
+ def gem_file
46
+ "gollum-#{name}-#{version}.gem"
47
+ end
48
+
49
+ def replace_header(head, header_name)
50
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
51
+ end
52
+
53
+ desc "Run specs."
54
+ RSpec::Core::RakeTask.new(:rspec) do |spec|
55
+ ruby_opts = "-w"
56
+ spec.pattern = 'spec/**/*_spec.rb'
57
+ spec.rspec_opts = ['--backtrace --color']
58
+ end
59
+
60
+ desc "Update version number and gemspec"
61
+ task :bump do
62
+ puts "Updated version to #{bump_version}"
63
+ # Execute does not invoke dependencies.
64
+ # Manually invoke gemspec then validate.
65
+ Rake::Task[:gemspec].execute
66
+ Rake::Task[:validate].execute
67
+ end
68
+
69
+ desc 'Create a release build'
70
+ task :release => :build do
71
+ unless `git branch` =~ /^\* master$/
72
+ puts "You must be on the master branch to release!"
73
+ exit!
74
+ end
75
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
76
+ sh "git pull --rebase origin master"
77
+ sh "git tag v#{version}"
78
+ sh "git push origin master"
79
+ sh "git push origin v#{version}"
80
+ sh "gem push pkg/#{gem_file}"
81
+ end
82
+
83
+ desc 'Publish to rubygems. Same as release'
84
+ task :publish => :release
85
+
86
+ desc 'Build gem'
87
+ task :build => :gemspec do
88
+ sh "mkdir -p pkg"
89
+ sh "gem build #{gemspec}"
90
+ sh "mv #{gem_file} pkg"
91
+ end
92
+
93
+ desc 'Update gemspec'
94
+ task :gemspec => :validate do
95
+ # read spec file and split out manifest section
96
+ spec = File.read(gemspec)
97
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
98
+
99
+ # replace name version and date
100
+ replace_header(head, :name)
101
+ replace_header(head, :date)
102
+
103
+ # determine file list from git ls-files
104
+ files = `git ls-files`.
105
+ split("\n").
106
+ sort.
107
+ reject { |file| file =~ /^\./ }.
108
+ reject { |file| file =~ /^(rdoc|pkg|spec|\.gitattributes|Guardfile)/ }.
109
+ map { |file| " #{file}" }.
110
+ join("\n")
111
+
112
+ # piece file back together and write
113
+ manifest = " s.files = %w(\n#{files}\n )\n"
114
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
115
+ File.open(gemspec, 'w') { |io| io.write(spec) }
116
+ puts "Updated #{gemspec}"
117
+ end
118
+
119
+ desc 'Validate lib files and version file'
120
+ task :validate do
121
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
122
+ unless libfiles.empty?
123
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
124
+ exit!
125
+ end
126
+ end
@@ -0,0 +1 @@
1
+ require 'rugged_adapter/git_layer_rugged.rb'
@@ -0,0 +1,660 @@
1
+ # ~*~ encoding: utf-8 ~*~
2
+
3
+ require 'rugged'
4
+ require 'ostruct'
5
+ require 'mime-types'
6
+
7
+ module Gollum
8
+
9
+ def self.set_git_timeout(time)
10
+ end
11
+
12
+ def self.set_git_max_filesize(size)
13
+ end
14
+
15
+ module Git
16
+
17
+ DEFAULT_MIME_TYPE = "text/plain"
18
+ class NoSuchShaFound < StandardError; end
19
+
20
+ class Actor
21
+
22
+ attr_accessor :name, :email
23
+
24
+ def self.default_actor
25
+ self.new("Gollum", "Gollum@wiki")
26
+ end
27
+
28
+ def initialize(name, email)
29
+ @name = name
30
+ @email = email
31
+ end
32
+
33
+ def output(time)
34
+ # implementation from grit
35
+ offset = time.utc_offset / 60
36
+ "%s <%s> %d %+.2d%.2d" % [
37
+ @name,
38
+ @email || "null",
39
+ time.to_i,
40
+ offset / 60,
41
+ offset.abs % 60]
42
+ end
43
+
44
+ def to_h
45
+ {:name => @name, :email => @email}
46
+ end
47
+
48
+ end
49
+
50
+ class Blob
51
+
52
+ attr_reader :mode
53
+ attr_reader :name
54
+ attr_reader :id
55
+
56
+ def self.create(repo, options)
57
+ blob = repo.git.lookup(options[:id])
58
+ self.new(blob, options)
59
+ end
60
+
61
+ def initialize(blob, options = {})
62
+ @blob = blob
63
+ @mode = options[:mode]
64
+ @name = options[:name]
65
+ @size = options[:size]
66
+ @id = blob.oid
67
+ end
68
+
69
+ def data
70
+ @content ||= @blob.content
71
+ end
72
+
73
+ def is_symlink
74
+ @mode == 0120000
75
+ end
76
+
77
+ def mime_type
78
+ guesses = MIME::Types.type_for(self.name) rescue []
79
+ guesses.first ? guesses.first.simplified : DEFAULT_MIME_TYPE
80
+ end
81
+
82
+ def size
83
+ @size || @blob.size
84
+ end
85
+
86
+ def symlink_target(base_path = nil)
87
+ target = data
88
+ new_path = ::File.expand_path(::File.join('..', target), base_path)
89
+ return new_path if ::File.file? new_path
90
+ nil
91
+ end
92
+ end
93
+
94
+ class Commit
95
+
96
+ def initialize(commit)
97
+ @commit = commit
98
+ end
99
+
100
+ def id
101
+ @commit.oid
102
+ end
103
+ alias_method :sha, :id
104
+ alias_method :to_s, :id
105
+
106
+ attr_reader :commit
107
+
108
+ def author
109
+ @author ||= Gollum::Git::Actor.new(@commit.author[:name], @commit.author[:email])
110
+ end
111
+
112
+ def authored_date
113
+ @commit.author[:time]
114
+ end
115
+
116
+ def message
117
+ @commit.message
118
+ end
119
+
120
+ def tree
121
+ Gollum::Git::Tree.new(@commit.tree)
122
+ end
123
+
124
+ def stats
125
+ @stats ||= build_stats
126
+ end
127
+
128
+ private
129
+
130
+ def build_stats
131
+ additions = 0
132
+ deletions = 0
133
+ total = 0
134
+ files = []
135
+ parent = @commit.parents.first
136
+ diff = Rugged::Tree.diff(@commit.tree.repo, parent ? parent.tree : nil, @commit.tree)
137
+ diff = diff.each_patch do |patch|
138
+ new_additions = patch.stat[1]
139
+ new_deletions = patch.stat[0]
140
+ additions += new_additions
141
+ deletions += new_deletions
142
+ total += patch.changes
143
+ files << [patch.delta.new_file[:path].force_encoding("UTF-8"), new_deletions, new_additions, patch.changes] # Rugged seems to generate the stat diffs in the other direciton than grit does by default, so switch the order of additions and deletions.
144
+ end
145
+ OpenStruct.new(:additions => additions, :deletions => deletions, :files => files, :id => id, :total => total)
146
+ end
147
+
148
+ end
149
+
150
+ class Git
151
+
152
+ # Rugged does not have a Git class, but the Repository class should allows us to do what's necessary.
153
+ def initialize(repo)
154
+ @repo = repo
155
+ end
156
+
157
+ def exist?
158
+ ::File.exists?(@repo.path)
159
+ end
160
+
161
+ def grep(query, options={})
162
+ ref = options[:ref] ? options[:ref] : "HEAD"
163
+ tree = @repo.lookup(sha_from_ref(ref)).tree
164
+ tree = @repo.lookup(tree[options[:path]][:oid]) if options[:path]
165
+ results = []
166
+ tree.walk_blobs(:postorder) do |root, entry|
167
+ blob = @repo.lookup(entry[:oid])
168
+ count = 0
169
+ blob.content.each_line do |line|
170
+ next unless line.force_encoding("UTF-8").match(/#{Regexp.escape(query)}/i)
171
+ count += 1
172
+ end
173
+ path = options[:path] ? ::File.join(options[:path], root, entry[:name]) : "#{root}#{entry[:name]}"
174
+ results << {:name => path, :count => count} unless count == 0
175
+ end
176
+ results
177
+ end
178
+
179
+ def rm(path, options = {})
180
+ index = @repo.index
181
+ index.write
182
+ ::File.unlink ::File.join(@repo.workdir, path)
183
+ end
184
+
185
+ def cat_file(options, sha)
186
+ @repo.lookup(sha).read_raw
187
+ end
188
+
189
+ def apply_patch(head_sha = 'HEAD', patch=nil)
190
+ false # Rewrite gollum-lib's revert so that it doesn't require a direct equivalent of Grit's apply_patch
191
+ end
192
+
193
+ def revert(path, sha1, sha2, ref)
194
+ # FIXME: See https://github.com/gollum/grit_adapter/pull/14
195
+ fail NotImplementedError
196
+ end
197
+
198
+ def checkout(path, ref = 'HEAD', options = {})
199
+ path = path.nil? ? path : [path]
200
+ options = options.merge({:paths => path, :strategy => :force})
201
+ if ref == 'HEAD'
202
+ @repo.checkout_head(options)
203
+ else
204
+ ref = "refs/heads/#{ref}" unless ref =~ /^refs\/heads\//
205
+ @repo.checkout_tree(sha_from_ref(ref), options)
206
+ end
207
+ end
208
+
209
+ def log(ref = 'refs/heads/master', path = nil, options = {})
210
+ default_options = {
211
+ :limit => options[:max_count] ? options[:max_count] : 10,
212
+ :offset => options[:skip] ? options[:skip] : 0,
213
+ :path => path,
214
+ :follow => false,
215
+ :skip_merges => false
216
+ }
217
+ options = default_options.merge(options)
218
+ options[:limit] ||= 0
219
+ options[:offset] ||= 0
220
+ sha = sha_from_ref(ref)
221
+ return [] if sha.nil?
222
+ begin
223
+ build_log(sha, options)
224
+ rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
225
+ # Return an empty array if the ref wasn't found
226
+ []
227
+ end
228
+ end
229
+
230
+ def versions_for_path(path = nil, ref = nil, options = {})
231
+ log(ref, path, options)
232
+ end
233
+
234
+ def ls_files(query, options = {})
235
+ ref = options[:ref] || "refs/heads/master"
236
+ tree = @repo.lookup(sha_from_ref(ref)).tree
237
+ tree = @repo.lookup(tree[options[:path]][:oid]) if options[:path]
238
+ results = []
239
+ tree.walk_blobs do |root, blob|
240
+ next unless blob[:name] =~ /#{query}/
241
+ path = options[:path] ? ::File.join(options[:path], root, blob[:name]) : "#{root}#{blob[:name]}"
242
+ results << path
243
+ end
244
+ results
245
+ end
246
+
247
+ def lookup(id)
248
+ @repo.lookup(id)
249
+ end
250
+
251
+ def ref_to_sha(query)
252
+ return query if sha?(query)
253
+ query = "refs/heads/#{query}" if !query.nil? && !(query =~ /^refs\/heads\//) && !(query == "HEAD")
254
+ begin
255
+ return @repo.rev_parse_oid(query)
256
+ rescue Rugged::ReferenceError, Rugged::InvalidError
257
+ return nil
258
+ end
259
+ end
260
+
261
+ def sha_or_commit_from_ref(ref, request_kind = nil)
262
+ sha = ref_to_sha(ref)
263
+ return nil if sha.nil?
264
+ object = @repo.lookup(sha)
265
+ if object.kind_of?(Rugged::Commit) then
266
+ return Gollum::Git::Commit.new(object) if request_kind == :commit
267
+ sha
268
+ elsif object.respond_to?(:target)
269
+ sha_or_commit_from_ref(object.target.oid, request_kind)
270
+ end
271
+ end
272
+ alias_method :sha_from_ref, :sha_or_commit_from_ref
273
+
274
+ def commit_from_ref(ref)
275
+ sha_or_commit_from_ref(ref, :commit)
276
+ end
277
+
278
+ def push(remote, branches = nil, options = {})
279
+ branches = [branches].flatten.map {|branch| "refs/heads/#{branch}" unless branch =~ /^refs\/heads\//}
280
+ @repo.push(remote, branches, options)
281
+ end
282
+
283
+ def pull(remote, branches = nil, options = {})
284
+ branches = [branches].flatten.map {|branch| "refs/heads/#{branch}" unless branch =~ /^refs\/heads\//}
285
+ r = @repo.remotes[remote]
286
+ r.fetch(branches, options)
287
+ branches.each do |branch|
288
+ branch_name = branch.match(/^refs\/heads\/(.*)/)[1]
289
+ remote_name = remote.match(/^(refs\/heads\/)?(.*)/)[2]
290
+ remote_ref = @repo.branches["#{remote_name}/#{branch_name}"].target
291
+ local_ref = @repo.branches[branch].target
292
+ index = @repo.merge_commits(local_ref, remote_ref)
293
+ options = { author: Actor.default_actor.to_h,
294
+ committer: Actor.default_actor.to_h,
295
+ message: "Merged branch #{branch} of #{remote}.",
296
+ parents: [local_ref, remote_ref],
297
+ tree: index.write_tree(@repo),
298
+ update_ref: branch
299
+ }
300
+ Rugged::Commit.create @repo, options
301
+ @repo.checkout(@repo.head.name, :strategy => :force) if !@repo.bare? && branch == @repo.head.name
302
+ end
303
+ end
304
+
305
+ private
306
+
307
+ def sha?(str)
308
+ !!(str =~ /^[0-9a-f]{40}$/)
309
+ end
310
+
311
+ # Return an array of log commits, given an SHA hash and a hash of
312
+ # options. From Gitlab::Git
313
+ def build_log(sha, options)
314
+ # Instantiate a Walker and add the SHA hash
315
+ walker = Rugged::Walker.new(@repo)
316
+ walker.push(sha)
317
+ commits = []
318
+ skipped = 0
319
+ current_path = options[:path]
320
+ current_path = nil if current_path == ''
321
+ limit = options[:limit].to_i
322
+ offset = options[:offset].to_i
323
+ skip_merges = options[:skip_merges]
324
+ walker.sorting(Rugged::SORT_DATE)
325
+
326
+ walker.each do |c|
327
+ break if limit > 0 && commits.length >= limit
328
+ if skip_merges
329
+ # Skip merge commits
330
+ next if c.parents.length > 1
331
+ end
332
+
333
+ if !current_path ||
334
+ commit_touches_path?(c, current_path, options[:follow], walker)
335
+ # This is a commit we care about, unless we haven't skipped enough
336
+ # yet
337
+ skipped += 1
338
+ commits.push(Gollum::Git::Commit.new(c)) if skipped > offset
339
+ end
340
+ end
341
+ walker.reset
342
+ commits
343
+ end
344
+
345
+ # Returns true if +commit+ introduced changes to +path+, using commit
346
+ # trees to make that determination. Uses the history simplification
347
+ # rules that `git log` uses by default, where a commit is omitted if it
348
+ # is TREESAME to any parent.
349
+ #
350
+ # If the +follow+ option is true and the file specified by +path+ was
351
+ # renamed, then the path value is set to the old path.
352
+ def commit_touches_path?(commit, path, follow, walker)
353
+ entry = tree_entry(commit, path)
354
+
355
+ if commit.parents.empty?
356
+ # This is the root commit, return true if it has +path+ in its tree
357
+ return entry != nil
358
+ end
359
+
360
+ num_treesame = 0
361
+ commit.parents.each do |parent|
362
+ parent_entry = tree_entry(parent, path)
363
+
364
+ # Only follow the first TREESAME parent for merge commits
365
+ if num_treesame > 0
366
+ walker.hide(parent)
367
+ next
368
+ end
369
+
370
+ if entry.nil? && parent_entry.nil?
371
+ num_treesame += 1
372
+ elsif entry && parent_entry && entry[:oid] == parent_entry[:oid]
373
+ num_treesame += 1
374
+ end
375
+ end
376
+
377
+ case num_treesame
378
+ when 0
379
+ detect_rename(commit, commit.parents.first, path) if follow
380
+ true
381
+ else false
382
+ end
383
+ end
384
+
385
+ # Find the entry for +path+ in the tree for +commit+
386
+ def tree_entry(commit, path)
387
+ pathname = Pathname.new(path)
388
+ tmp_entry = nil
389
+
390
+ pathname.each_filename do |dir|
391
+ tmp_entry = if tmp_entry.nil?
392
+ commit.tree[dir]
393
+ else
394
+ @repo.lookup(tmp_entry[:oid])[dir]
395
+ end
396
+
397
+ return nil unless tmp_entry
398
+ end
399
+ tmp_entry
400
+ end
401
+
402
+ # Compare +commit+ and +parent+ for +path+. If +path+ is a file and was
403
+ # renamed in +commit+, then set +path+ to the old filename.
404
+ def detect_rename(commit, parent, path)
405
+ diff = parent.diff(commit, paths: [path], disable_pathspec_match: true)
406
+
407
+ # If +path+ is a filename, not a directory, then we should only have
408
+ # one delta. We don't need to follow renames for directories.
409
+ return nil if diff.each_delta.count > 1
410
+
411
+ delta = diff.each_delta.first
412
+ if delta.added?
413
+ full_diff = parent.diff(commit)
414
+ full_diff.find_similar!
415
+
416
+ full_diff.each_delta do |full_delta|
417
+ if full_delta.renamed? && path == full_delta.new_file[:path]
418
+ # Look for the old path in ancestors
419
+ path.replace(full_delta.old_file[:path])
420
+ end
421
+ end
422
+ end
423
+ end
424
+
425
+ end
426
+
427
+ class Index
428
+
429
+ def initialize(index, repo)
430
+ @index = index
431
+ @rugged_repo = repo
432
+ @treemap = {}
433
+ end
434
+
435
+ def delete(path)
436
+ @index.remove_all(path)
437
+ update_treemap(path, false)
438
+ false
439
+ end
440
+
441
+ def add(path, data)
442
+ blob = @rugged_repo.write(data, :blob)
443
+ @index.add(:path => path, :oid => blob, :mode => 0100644)
444
+ update_treemap(path, data)
445
+ data
446
+ end
447
+
448
+ def index
449
+ @index
450
+ end
451
+
452
+ def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'refs/heads/master')
453
+ commit_options = {}
454
+ head = "refs/heads/#{head}" if head && head !~ %r(^refs/heads/)
455
+ parents = get_parents(parents, head) || []
456
+ actor = Gollum::Git::Actor.default_actor if actor.nil?
457
+ commit_options[:tree] = @index.write_tree
458
+ commit_options[:author] = actor.to_h
459
+ commit_options[:committer] = actor.to_h
460
+ commit_options[:message] = message.to_s
461
+ commit_options[:parents] = parents
462
+ commit_options[:update_ref] = head
463
+ Rugged::Commit.create(@rugged_repo, commit_options)
464
+ end
465
+
466
+ def tree
467
+ @treemap
468
+ end
469
+
470
+ def read_tree(id)
471
+ id = Gollum::Git::Git.new(@rugged_repo).ref_to_sha(id)
472
+ return nil if id.nil?
473
+ current_tree = @rugged_repo.lookup(id)
474
+ current_tree = current_tree.tree unless current_tree.is_a?(Rugged::Tree)
475
+ @index.read_tree(current_tree)
476
+ @current_tree = Gollum::Git::Tree.new(current_tree)
477
+ end
478
+
479
+ def current_tree
480
+ @current_tree
481
+ end
482
+
483
+ private
484
+
485
+ def get_parents(parents, head)
486
+ if parents
487
+ parents.map{|parent| parent.commit}
488
+ elsif ref = @rugged_repo.references[head]
489
+ ref = ref.target
490
+ ref = ref.target if ref.respond_to?(:target)
491
+ [ref]
492
+ end
493
+ end
494
+
495
+ def update_treemap(path, data)
496
+ # From RJGit::Plumbing::Index
497
+ path = path[1..-1] if path[0] == ::File::SEPARATOR
498
+ path = path.split(::File::SEPARATOR)
499
+ last = path.pop
500
+
501
+ current = @treemap
502
+
503
+ path.each do |dir|
504
+ current[dir] ||= {}
505
+ node = current[dir]
506
+ current = node
507
+ end
508
+
509
+ current[last] = data
510
+ @treemap
511
+ end
512
+
513
+ end
514
+
515
+ class Ref
516
+ def initialize(ref)
517
+ @ref = ref
518
+ end
519
+
520
+ def name
521
+ @ref.name
522
+ end
523
+
524
+ def commit
525
+ Gollum::Git::Commit.new(@ref.target)
526
+ end
527
+
528
+ end
529
+
530
+ class Repo
531
+
532
+ def initialize(path, options)
533
+ begin
534
+ @repo = Rugged::Repository.new(path, options)
535
+ #rescue Grit::InvalidGitRepositoryError
536
+ # raise Gollum::InvalidGitRepositoryError
537
+ #rescue Grit::NoSuchPathError
538
+ # raise Gollum::NoSuchPathError
539
+ end
540
+ end
541
+
542
+ def self.init(path)
543
+ Rugged::Repository.init_at(path, false)
544
+ self.new(path, :is_bare => false)
545
+ end
546
+
547
+ def self.init_bare(path)
548
+ Rugged::Repository.init_at(path, true)
549
+ self.new(path, :is_bare => true)
550
+ end
551
+
552
+ def bare
553
+ @repo.bare?
554
+ end
555
+
556
+ def config
557
+ @repo.config
558
+ end
559
+
560
+ def git
561
+ @git ||= Gollum::Git::Git.new(@repo)
562
+ end
563
+
564
+ def commit(id)
565
+ git.commit_from_ref(id)
566
+ end
567
+
568
+ def commits(start = 'refs/heads/master', max_count = 10, skip = 0)
569
+ git.log(start, nil, :max_count => max_count, :skip => skip)
570
+ end
571
+
572
+ def head
573
+ Gollum::Git::Ref.new(@repo.head)
574
+ end
575
+
576
+ def index
577
+ @index ||= Gollum::Git::Index.new(@repo.index, @repo)
578
+ end
579
+
580
+ def diff(sha1, sha2, *paths)
581
+ opts = path == nil ? {} : {:path => path}
582
+ patches = @repo.diff(sha1, sha2, opts).patches
583
+ if not paths.empty?
584
+ patches.keep_if { |p| paths.include? p.delta.new_file[:path] }
585
+ end
586
+ patches.map {|patch| OpenStruct.new(:diff => patch.to_s.split("\n")[2..-1].join("\n").force_encoding("UTF-8"))}.reverse # First remove two superfluous lines. Rugged seems to order the diffs differently than Grit, so reverse.
587
+ end
588
+
589
+ def log(commit = 'refs/heads/master', path = nil, options = {})
590
+ git.log(commit, path, options)
591
+ end
592
+
593
+ def lstree(sha, options = {})
594
+ results = []
595
+ @repo.lookup(sha).tree.walk(:postorder) do |root, entry|
596
+ entry[:sha] = entry[:oid]
597
+ entry[:mode] = entry[:filemode].to_s(8)
598
+ entry[:type] = entry[:type].to_s
599
+ entry[:path] = "#{root}#{entry[:name]}"
600
+ results << entry
601
+ end
602
+ results
603
+ end
604
+
605
+ def path
606
+ @repo.path
607
+ end
608
+
609
+ # Checkout branch and if necessary first create it. Currently used only in gollum-lib's tests.
610
+ def update_ref(ref, commit_sha)
611
+ ref = "refs/heads/#{ref}" unless ref =~ /^refs\/heads\//
612
+ if _ref = @repo.references[ref]
613
+ @repo.references.update(_ref, commit_sha)
614
+ else
615
+ @repo.create_branch(ref, commit_sha)
616
+ @repo.checkout(ref, :strategy => :force) unless @repo.bare?
617
+ end
618
+ end
619
+ end
620
+
621
+ class Tree
622
+
623
+ def initialize(tree)
624
+ @tree = tree
625
+ end
626
+
627
+ def keys
628
+ @tree.map{|entry| entry[:name]}
629
+ end
630
+
631
+ def [](i)
632
+ @tree[i]
633
+ end
634
+
635
+ def id
636
+ @tree.oid
637
+ end
638
+
639
+ def /(file)
640
+ return self if file == '/'
641
+ begin
642
+ obj = @tree.path(file)
643
+ rescue Rugged::TreeError
644
+ return nil
645
+ end
646
+ return nil if obj.nil?
647
+ obj = @tree.owner.lookup(obj[:oid])
648
+ obj.is_a?(Rugged::Tree) ? Gollum::Git::Tree.new(obj) : Gollum::Git::Blob.new(obj)
649
+ end
650
+
651
+ def blobs
652
+ blobs = []
653
+ @tree.each_blob {|blob| blobs << Gollum::Git::Blob.new(@tree.owner.lookup(blob[:oid]), blob) }
654
+ blobs
655
+ end
656
+
657
+ end
658
+
659
+ end
660
+ end
@@ -0,0 +1,7 @@
1
+ module Gollum
2
+ module Lib
3
+ module Git
4
+ VERSION = '0.4.4'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rugged_adapter/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "gitlab-gollum-rugged_adapter"
7
+ s.version = Gollum::Lib::Git::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Bart Kamphorst, Dawa Ometto"]
10
+ s.email = ["fjlopez@gitlab.com"]
11
+ s.homepage = "https://gitlab.com/gitlab-org/gitlab-gollum-rugged_adapter"
12
+ s.summary = %q{Adapter for Gollum to use Rugged (libgit2) at the backend.}
13
+ s.description = %q{Adapter for Gollum to use Rugged (libgit2) at the backend.}
14
+ s.license = "MIT"
15
+
16
+ s.add_runtime_dependency 'rugged', '~> 0.25'
17
+ s.add_runtime_dependency 'mime-types', '>= 1.15'
18
+ s.add_development_dependency "rspec", "3.4.0"
19
+
20
+ s.files = Dir['lib/**/*.rb'] + ["README.md", "Gemfile"]
21
+ s.require_paths = ["lib"]
22
+
23
+ # = MANIFEST =
24
+ s.files = %w(
25
+ Gemfile
26
+ LICENSE
27
+ README.md
28
+ Rakefile
29
+ lib/rugged_adapter.rb
30
+ lib/rugged_adapter/git_layer_rugged.rb
31
+ lib/rugged_adapter/version.rb
32
+ rugged_adapter.gemspec
33
+ )
34
+ # = MANIFEST =
35
+
36
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gitlab-gollum-rugged_adapter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.4
5
+ platform: ruby
6
+ authors:
7
+ - Bart Kamphorst, Dawa Ometto
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rugged
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.25'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.25'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mime-types
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '1.15'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '1.15'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 3.4.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 3.4.0
55
+ description: Adapter for Gollum to use Rugged (libgit2) at the backend.
56
+ email:
57
+ - fjlopez@gitlab.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - Gemfile
63
+ - LICENSE
64
+ - README.md
65
+ - Rakefile
66
+ - lib/rugged_adapter.rb
67
+ - lib/rugged_adapter/git_layer_rugged.rb
68
+ - lib/rugged_adapter/version.rb
69
+ - rugged_adapter.gemspec
70
+ homepage: https://gitlab.com/gitlab-org/gitlab-gollum-rugged_adapter
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.5.2
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Adapter for Gollum to use Rugged (libgit2) at the backend.
94
+ test_files: []