summaryrefslogtreecommitdiff
path: root/lib/gitlab/git/tree.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/git/tree.rb')
-rw-r--r--lib/gitlab/git/tree.rb104
1 files changed, 104 insertions, 0 deletions
diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb
new file mode 100644
index 00000000000..f7450e8b58f
--- /dev/null
+++ b/lib/gitlab/git/tree.rb
@@ -0,0 +1,104 @@
+module Gitlab
+ module Git
+ class Tree
+ include Gitlab::Git::EncodingHelper
+
+ attr_accessor :id, :root_id, :name, :path, :type,
+ :mode, :commit_id, :submodule_url
+
+ class << self
+ # Get list of tree objects
+ # for repository based on commit sha and path
+ # Uses rugged for raw objects
+ def where(repository, sha, path = nil)
+ path = nil if path == '' || path == '/'
+
+ commit = repository.lookup(sha)
+ root_tree = commit.tree
+
+ tree = if path
+ id = find_id_by_path(repository, root_tree.oid, path)
+ if id
+ repository.lookup(id)
+ else
+ []
+ end
+ else
+ root_tree
+ end
+
+ tree.map do |entry|
+ new(
+ id: entry[:oid],
+ root_id: root_tree.oid,
+ name: entry[:name],
+ type: entry[:type],
+ mode: entry[:filemode],
+ path: path ? File.join(path, entry[:name]) : entry[:name],
+ commit_id: sha,
+ )
+ end
+ end
+
+ # Recursive search of tree id for path
+ #
+ # Ex.
+ # blog/ # oid: 1a
+ # app/ # oid: 2a
+ # models/ # oid: 3a
+ # views/ # oid: 4a
+ #
+ #
+ # Tree.find_id_by_path(repo, '1a', 'app/models') # => '3a'
+ #
+ def find_id_by_path(repository, root_id, path)
+ root_tree = repository.lookup(root_id)
+ path_arr = path.split('/')
+
+ entry = root_tree.find do |entry|
+ entry[:name] == path_arr[0] && entry[:type] == :tree
+ end
+
+ return nil unless entry
+
+ if path_arr.size > 1
+ path_arr.shift
+ find_id_by_path(repository, entry[:oid], path_arr.join('/'))
+ else
+ entry[:oid]
+ end
+ end
+ end
+
+ def initialize(options)
+ %w(id root_id name path type mode commit_id).each do |key|
+ self.send("#{key}=", options[key.to_sym])
+ end
+ end
+
+ def name
+ encode! @name
+ end
+
+ def dir?
+ type == :tree
+ end
+
+ def file?
+ type == :blob
+ end
+
+ def submodule?
+ type == :commit
+ end
+
+ def readme?
+ name =~ /^readme/i
+ end
+
+ def contributing?
+ name =~ /^contributing/i
+ end
+ end
+ end
+end