BigW Consortium Gitlab

tree.rb 2.47 KB
Newer Older
Robert Speicher committed
1 2 3
module Gitlab
  module Git
    class Tree
4
      include Gitlab::EncodingHelper
Robert Speicher committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

      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
20
                   id = find_id_by_path(repository, root_tree.oid, path)
Robert Speicher committed
21 22 23 24 25 26 27 28 29 30
                   if id
                     repository.lookup(id)
                   else
                     []
                   end
                 else
                   root_tree
                 end

          tree.map do |entry|
31
            new(
Robert Speicher committed
32 33 34 35
              id: entry[:oid],
              root_id: root_tree.oid,
              name: entry[:name],
              type: entry[:type],
36
              mode: entry[:filemode].to_s(8),
Robert Speicher committed
37
              path: path ? File.join(path, entry[:name]) : entry[:name],
38
              commit_id: sha
Robert Speicher committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
            )
          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