Commit 3471e26fb218ce3f827c652792ac6c429c861fc0
Exists in
master
and in
4 other branches
Merge branch 'feature/move_gitlab_git' of /home/git/repositories/gitlab/gitlabhq
Showing
18 changed files
with
13 additions
and
871 deletions
Show diff stats
Gemfile
| ... | ... | @@ -22,9 +22,9 @@ gem 'omniauth-twitter' |
| 22 | 22 | gem 'omniauth-github' |
| 23 | 23 | |
| 24 | 24 | # Extracting information from a git repository |
| 25 | -# Since gollum requires grit we cannot use gitlab-grit gem name any more. Use grit instead | |
| 25 | +# We cannot use original git since some bugs | |
| 26 | 26 | gem "grit", '~> 2.5.0', git: 'https://github.com/gitlabhq/grit.git', ref: '42297cdcee16284d2e4eff23d41377f52fc28b9d' |
| 27 | -gem 'grit_ext', '~> 0.8.1' | |
| 27 | +gem 'gitlab_git', '~> 1.0.3' | |
| 28 | 28 | |
| 29 | 29 | # Ruby/Rack Git Smart-HTTP Server Handler |
| 30 | 30 | gem 'gitlab-grack', '~> 1.0.0', require: 'grack' | ... | ... |
Gemfile.lock
| ... | ... | @@ -164,6 +164,11 @@ GEM |
| 164 | 164 | gitlab-pygments.rb (0.3.2) |
| 165 | 165 | posix-spawn (~> 0.3.6) |
| 166 | 166 | yajl-ruby (~> 1.1.0) |
| 167 | + gitlab_git (1.0.3) | |
| 168 | + activesupport (~> 3.2.13) | |
| 169 | + github-linguist (~> 2.3.4) | |
| 170 | + grit (~> 2.5.0) | |
| 171 | + grit_ext (~> 0.8.1) | |
| 167 | 172 | gitlab_meta (5.0) |
| 168 | 173 | gitlab_omniauth-ldap (1.0.2) |
| 169 | 174 | net-ldap (~> 0.2.2) |
| ... | ... | @@ -501,6 +506,7 @@ DEPENDENCIES |
| 501 | 506 | github-markup (~> 0.7.4) |
| 502 | 507 | gitlab-grack (~> 1.0.0) |
| 503 | 508 | gitlab-pygments.rb (~> 0.3.2) |
| 509 | + gitlab_git (~> 1.0.3) | |
| 504 | 510 | gitlab_meta (= 5.0) |
| 505 | 511 | gitlab_omniauth-ldap (= 1.0.2) |
| 506 | 512 | gollum-lib (~> 1.0.0) |
| ... | ... | @@ -508,7 +514,6 @@ DEPENDENCIES |
| 508 | 514 | grape (~> 0.3.1) |
| 509 | 515 | grape-entity (~> 0.2.0) |
| 510 | 516 | grit (~> 2.5.0)! |
| 511 | - grit_ext (~> 0.8.1) | |
| 512 | 517 | growl |
| 513 | 518 | guard-rspec |
| 514 | 519 | guard-spinach | ... | ... |
VERSION
config/initializers/3_grit_ext.rb
config/initializers/5_backend.rb
| ... | ... | @@ -6,3 +6,6 @@ require Rails.root.join("lib", "gitlab", "backend", "shell") |
| 6 | 6 | |
| 7 | 7 | # GitLab shell adapter |
| 8 | 8 | require Rails.root.join("lib", "gitlab", "backend", "shell_adapter") |
| 9 | + | |
| 10 | +# Gitlab Git repos path | |
| 11 | +Gitlab::Git::Repository.repos_path = Gitlab.config.gitlab_shell.repos_path | ... | ... |
lib/gitlab/git/blame.rb
| ... | ... | @@ -1,23 +0,0 @@ |
| 1 | -module Gitlab | |
| 2 | - module Git | |
| 3 | - class Blame | |
| 4 | - | |
| 5 | - attr_accessor :repository, :sha, :path | |
| 6 | - | |
| 7 | - def initialize(repository, sha, path) | |
| 8 | - @repository, @sha, @path = repository, sha, path | |
| 9 | - end | |
| 10 | - | |
| 11 | - def each | |
| 12 | - raw_blame = Grit::Blob.blame(repository.repo, sha, path) | |
| 13 | - | |
| 14 | - raw_blame.each do |commit, lines| | |
| 15 | - next unless commit | |
| 16 | - | |
| 17 | - commit = Gitlab::Git::Commit.new(commit) | |
| 18 | - yield(commit, lines) | |
| 19 | - end | |
| 20 | - end | |
| 21 | - end | |
| 22 | - end | |
| 23 | -end |
lib/gitlab/git/blob.rb
| ... | ... | @@ -1,42 +0,0 @@ |
| 1 | -module Gitlab | |
| 2 | - module Git | |
| 3 | - class Blob | |
| 4 | - include Linguist::BlobHelper | |
| 5 | - | |
| 6 | - attr_accessor :raw_blob | |
| 7 | - | |
| 8 | - delegate :name, to: :raw_blob | |
| 9 | - | |
| 10 | - def initialize(repository, sha, ref, path) | |
| 11 | - @repository, @sha, @ref = repository, sha, ref | |
| 12 | - | |
| 13 | - @commit = @repository.commit(sha) | |
| 14 | - @raw_blob = @repository.tree(@commit, path) | |
| 15 | - end | |
| 16 | - | |
| 17 | - def data | |
| 18 | - if raw_blob | |
| 19 | - raw_blob.data | |
| 20 | - else | |
| 21 | - nil | |
| 22 | - end | |
| 23 | - end | |
| 24 | - | |
| 25 | - def exists? | |
| 26 | - raw_blob | |
| 27 | - end | |
| 28 | - | |
| 29 | - def empty? | |
| 30 | - data.blank? | |
| 31 | - end | |
| 32 | - | |
| 33 | - def mode | |
| 34 | - raw_blob.mode | |
| 35 | - end | |
| 36 | - | |
| 37 | - def size | |
| 38 | - raw_blob.size | |
| 39 | - end | |
| 40 | - end | |
| 41 | - end | |
| 42 | -end |
lib/gitlab/git/commit.rb
| ... | ... | @@ -1,127 +0,0 @@ |
| 1 | -# Gitlab::Git::Commit is a wrapper around native Grit::Commit object | |
| 2 | -# We dont want to use grit objects inside app/ | |
| 3 | -# It helps us easily migrate to rugged in future | |
| 4 | -module Gitlab | |
| 5 | - module Git | |
| 6 | - class Commit | |
| 7 | - attr_accessor :raw_commit, :head, :refs, | |
| 8 | - :id, :authored_date, :committed_date, :message, | |
| 9 | - :author_name, :author_email, :parent_ids, | |
| 10 | - :committer_name, :committer_email | |
| 11 | - | |
| 12 | - delegate :parents, :tree, :stats, :to_patch, | |
| 13 | - to: :raw_commit | |
| 14 | - | |
| 15 | - def initialize(raw_commit, head = nil) | |
| 16 | - raise "Nil as raw commit passed" unless raw_commit | |
| 17 | - | |
| 18 | - if raw_commit.is_a?(Hash) | |
| 19 | - init_from_hash(raw_commit) | |
| 20 | - else | |
| 21 | - init_from_grit(raw_commit) | |
| 22 | - end | |
| 23 | - | |
| 24 | - @head = head | |
| 25 | - end | |
| 26 | - | |
| 27 | - def serialize_keys | |
| 28 | - @serialize_keys ||= %w(id authored_date committed_date author_name author_email committer_name committer_email message parent_ids).map(&:to_sym) | |
| 29 | - end | |
| 30 | - | |
| 31 | - def sha | |
| 32 | - id | |
| 33 | - end | |
| 34 | - | |
| 35 | - def short_id(length = 10) | |
| 36 | - id.to_s[0..length] | |
| 37 | - end | |
| 38 | - | |
| 39 | - def safe_message | |
| 40 | - @safe_message ||= message | |
| 41 | - end | |
| 42 | - | |
| 43 | - def created_at | |
| 44 | - committed_date | |
| 45 | - end | |
| 46 | - | |
| 47 | - # Was this commit committed by a different person than the original author? | |
| 48 | - def different_committer? | |
| 49 | - author_name != committer_name || author_email != committer_email | |
| 50 | - end | |
| 51 | - | |
| 52 | - def parent_id | |
| 53 | - parent_ids.first | |
| 54 | - end | |
| 55 | - | |
| 56 | - # Shows the diff between the commit's parent and the commit. | |
| 57 | - # | |
| 58 | - # Cuts out the header and stats from #to_patch and returns only the diff. | |
| 59 | - def to_diff | |
| 60 | - # see Grit::Commit#show | |
| 61 | - patch = to_patch | |
| 62 | - | |
| 63 | - # discard lines before the diff | |
| 64 | - lines = patch.split("\n") | |
| 65 | - while !lines.first.start_with?("diff --git") do | |
| 66 | - lines.shift | |
| 67 | - end | |
| 68 | - lines.pop if lines.last =~ /^[\d.]+$/ # Git version | |
| 69 | - lines.pop if lines.last == "-- " # end of diff | |
| 70 | - lines.join("\n") | |
| 71 | - end | |
| 72 | - | |
| 73 | - def has_zero_stats? | |
| 74 | - stats.total.zero? | |
| 75 | - rescue | |
| 76 | - true | |
| 77 | - end | |
| 78 | - | |
| 79 | - def no_commit_message | |
| 80 | - "--no commit message" | |
| 81 | - end | |
| 82 | - | |
| 83 | - def to_hash | |
| 84 | - hash = {} | |
| 85 | - | |
| 86 | - keys = serialize_keys | |
| 87 | - | |
| 88 | - keys.each do |key| | |
| 89 | - hash[key] = send(key) | |
| 90 | - end | |
| 91 | - | |
| 92 | - hash | |
| 93 | - end | |
| 94 | - | |
| 95 | - def date | |
| 96 | - committed_date | |
| 97 | - end | |
| 98 | - | |
| 99 | - def diffs | |
| 100 | - raw_commit.diffs.map { |diff| Gitlab::Git::Diff.new(diff) } | |
| 101 | - end | |
| 102 | - | |
| 103 | - private | |
| 104 | - | |
| 105 | - def init_from_grit(grit) | |
| 106 | - @raw_commit = grit | |
| 107 | - @id = grit.id | |
| 108 | - @message = grit.message | |
| 109 | - @authored_date = grit.authored_date | |
| 110 | - @committed_date = grit.committed_date | |
| 111 | - @author_name = grit.author.name | |
| 112 | - @author_email = grit.author.email | |
| 113 | - @committer_name = grit.committer.name | |
| 114 | - @committer_email = grit.committer.email | |
| 115 | - @parent_ids = grit.parents.map(&:id) | |
| 116 | - end | |
| 117 | - | |
| 118 | - def init_from_hash(hash) | |
| 119 | - raw_commit = hash.symbolize_keys | |
| 120 | - | |
| 121 | - serialize_keys.each do |key| | |
| 122 | - send(:"#{key}=", raw_commit[key.to_sym]) | |
| 123 | - end | |
| 124 | - end | |
| 125 | - end | |
| 126 | - end | |
| 127 | -end |
lib/gitlab/git/compare.rb
| ... | ... | @@ -1,35 +0,0 @@ |
| 1 | -module Gitlab | |
| 2 | - module Git | |
| 3 | - class Compare | |
| 4 | - attr_accessor :commits, :commit, :diffs, :same | |
| 5 | - | |
| 6 | - def initialize(repository, from, to) | |
| 7 | - @commits, @diffs = [], [] | |
| 8 | - @commit = nil | |
| 9 | - @same = false | |
| 10 | - | |
| 11 | - return unless from && to | |
| 12 | - | |
| 13 | - first = repository.commit(to.try(:strip)) | |
| 14 | - last = repository.commit(from.try(:strip)) | |
| 15 | - | |
| 16 | - return unless first && last | |
| 17 | - | |
| 18 | - if first.id == last.id | |
| 19 | - @same = true | |
| 20 | - return | |
| 21 | - end | |
| 22 | - | |
| 23 | - @commit = first | |
| 24 | - @commits = repository.commits_between(last.id, first.id) | |
| 25 | - | |
| 26 | - @diffs = if @commits.size > 100 | |
| 27 | - [] | |
| 28 | - else | |
| 29 | - repository.repo.diff(last.id, first.id) rescue [] | |
| 30 | - end | |
| 31 | - end | |
| 32 | - end | |
| 33 | - end | |
| 34 | -end | |
| 35 | - |
lib/gitlab/git/diff.rb
| ... | ... | @@ -1,63 +0,0 @@ |
| 1 | -# Gitlab::Git::Diff is a wrapper around native Grit::Diff object | |
| 2 | -# We dont want to use grit objects inside app/ | |
| 3 | -# It helps us easily migrate to rugged in future | |
| 4 | -module Gitlab | |
| 5 | - module Git | |
| 6 | - class Diff | |
| 7 | - BROKEN_DIFF = "--broken-diff" | |
| 8 | - | |
| 9 | - attr_accessor :raw_diff | |
| 10 | - | |
| 11 | - # Diff properties | |
| 12 | - attr_accessor :old_path, :new_path, :a_mode, :b_mode, :diff | |
| 13 | - | |
| 14 | - # Stats properties | |
| 15 | - attr_accessor :new_file, :renamed_file, :deleted_file | |
| 16 | - | |
| 17 | - def initialize(raw_diff) | |
| 18 | - raise "Nil as raw diff passed" unless raw_diff | |
| 19 | - | |
| 20 | - if raw_diff.is_a?(Hash) | |
| 21 | - init_from_hash(raw_diff) | |
| 22 | - else | |
| 23 | - init_from_grit(raw_diff) | |
| 24 | - end | |
| 25 | - end | |
| 26 | - | |
| 27 | - def serialize_keys | |
| 28 | - @serialize_keys ||= %w(diff new_path old_path a_mode b_mode new_file renamed_file deleted_file).map(&:to_sym) | |
| 29 | - end | |
| 30 | - | |
| 31 | - def to_hash | |
| 32 | - hash = {} | |
| 33 | - | |
| 34 | - keys = serialize_keys | |
| 35 | - | |
| 36 | - keys.each do |key| | |
| 37 | - hash[key] = send(key) | |
| 38 | - end | |
| 39 | - | |
| 40 | - hash | |
| 41 | - end | |
| 42 | - | |
| 43 | - private | |
| 44 | - | |
| 45 | - def init_from_grit(grit) | |
| 46 | - @raw_diff = grit | |
| 47 | - | |
| 48 | - serialize_keys.each do |key| | |
| 49 | - send(:"#{key}=", grit.send(key)) | |
| 50 | - end | |
| 51 | - end | |
| 52 | - | |
| 53 | - def init_from_hash(hash) | |
| 54 | - raw_diff = hash.symbolize_keys | |
| 55 | - | |
| 56 | - serialize_keys.each do |key| | |
| 57 | - send(:"#{key}=", raw_diff[key.to_sym]) | |
| 58 | - end | |
| 59 | - end | |
| 60 | - end | |
| 61 | - end | |
| 62 | -end | |
| 63 | - |
lib/gitlab/git/repository.rb
| ... | ... | @@ -1,221 +0,0 @@ |
| 1 | -# Gitlab::Git::Gitlab::Git::Commit is a wrapper around native Grit::Repository object | |
| 2 | -# We dont want to use grit objects inside app/ | |
| 3 | -# It helps us easily migrate to rugged in future | |
| 4 | -module Gitlab | |
| 5 | - module Git | |
| 6 | - class Repository | |
| 7 | - include Gitlab::Popen | |
| 8 | - | |
| 9 | - class NoRepository < StandardError; end | |
| 10 | - | |
| 11 | - # Repository directory name with namespace direcotry | |
| 12 | - # Examples: | |
| 13 | - # gitlab/gitolite | |
| 14 | - # diaspora | |
| 15 | - # | |
| 16 | - attr_accessor :path_with_namespace | |
| 17 | - | |
| 18 | - # Grit repo object | |
| 19 | - attr_accessor :repo | |
| 20 | - | |
| 21 | - # Default branch in the repository | |
| 22 | - attr_accessor :root_ref | |
| 23 | - | |
| 24 | - def initialize(path_with_namespace, root_ref = 'master') | |
| 25 | - @root_ref = root_ref || "master" | |
| 26 | - @path_with_namespace = path_with_namespace | |
| 27 | - | |
| 28 | - # Init grit repo object | |
| 29 | - repo | |
| 30 | - end | |
| 31 | - | |
| 32 | - def raw | |
| 33 | - repo | |
| 34 | - end | |
| 35 | - | |
| 36 | - def path_to_repo | |
| 37 | - @path_to_repo ||= File.join(repos_path, "#{path_with_namespace}.git") | |
| 38 | - end | |
| 39 | - | |
| 40 | - def repos_path | |
| 41 | - Gitlab.config.gitlab_shell.repos_path | |
| 42 | - end | |
| 43 | - | |
| 44 | - def repo | |
| 45 | - @repo ||= Grit::Repo.new(path_to_repo) | |
| 46 | - rescue Grit::NoSuchPathError | |
| 47 | - raise NoRepository.new('no repository for such path') | |
| 48 | - end | |
| 49 | - | |
| 50 | - def commit(commit_id = nil) | |
| 51 | - commit = if commit_id | |
| 52 | - # Find repo.refs first, | |
| 53 | - # because if commit_id is "tag name", | |
| 54 | - # repo.commit(commit_id) returns wrong commit sha | |
| 55 | - # that is git tag object sha. | |
| 56 | - ref = repo.refs.find {|r| r.name == commit_id} | |
| 57 | - if ref | |
| 58 | - ref.commit | |
| 59 | - else | |
| 60 | - repo.commit(commit_id) | |
| 61 | - end | |
| 62 | - else | |
| 63 | - repo.commits(root_ref).first | |
| 64 | - end | |
| 65 | - | |
| 66 | - decorate_commit(commit) if commit | |
| 67 | - end | |
| 68 | - | |
| 69 | - def commits_with_refs(n = 20) | |
| 70 | - commits = repo.branches.map { |ref| decorate_commit(ref.commit, ref) } | |
| 71 | - | |
| 72 | - commits.sort! do |x, y| | |
| 73 | - y.committed_date <=> x.committed_date | |
| 74 | - end | |
| 75 | - | |
| 76 | - commits[0..n] | |
| 77 | - end | |
| 78 | - | |
| 79 | - def commits(ref, path = nil, limit = nil, offset = nil) | |
| 80 | - if path.present? | |
| 81 | - repo.log(ref, path, max_count: limit, skip: offset, follow: true) | |
| 82 | - elsif limit && offset | |
| 83 | - repo.commits(ref, limit.to_i, offset.to_i) | |
| 84 | - else | |
| 85 | - repo.commits(ref) | |
| 86 | - end.map{ |c| decorate_commit(c) } | |
| 87 | - end | |
| 88 | - | |
| 89 | - def commits_between(from, to) | |
| 90 | - repo.commits_between(from, to).map { |c| decorate_commit(c) } | |
| 91 | - end | |
| 92 | - | |
| 93 | - def last_commit_for(ref, path = nil) | |
| 94 | - commits(ref, path, 1).first | |
| 95 | - end | |
| 96 | - | |
| 97 | - # Returns an Array of branch names | |
| 98 | - # sorted by name ASC | |
| 99 | - def branch_names | |
| 100 | - branches.map(&:name) | |
| 101 | - end | |
| 102 | - | |
| 103 | - # Returns an Array of Branches | |
| 104 | - def branches | |
| 105 | - repo.branches.sort_by(&:name) | |
| 106 | - end | |
| 107 | - | |
| 108 | - # Returns an Array of tag names | |
| 109 | - def tag_names | |
| 110 | - repo.tags.collect(&:name).sort.reverse | |
| 111 | - end | |
| 112 | - | |
| 113 | - # Returns an Array of Tags | |
| 114 | - def tags | |
| 115 | - repo.tags.sort_by(&:name).reverse | |
| 116 | - end | |
| 117 | - | |
| 118 | - # Returns an Array of branch and tag names | |
| 119 | - def ref_names | |
| 120 | - [branch_names + tag_names].flatten | |
| 121 | - end | |
| 122 | - | |
| 123 | - def heads | |
| 124 | - @heads ||= repo.heads | |
| 125 | - end | |
| 126 | - | |
| 127 | - def tree(fcommit, path = nil) | |
| 128 | - fcommit = commit if fcommit == :head | |
| 129 | - tree = fcommit.tree | |
| 130 | - path ? (tree / path) : tree | |
| 131 | - end | |
| 132 | - | |
| 133 | - def has_commits? | |
| 134 | - !!commit | |
| 135 | - rescue Grit::NoSuchPathError | |
| 136 | - false | |
| 137 | - end | |
| 138 | - | |
| 139 | - def empty? | |
| 140 | - !has_commits? | |
| 141 | - end | |
| 142 | - | |
| 143 | - # Discovers the default branch based on the repository's available branches | |
| 144 | - # | |
| 145 | - # - If no branches are present, returns nil | |
| 146 | - # - If one branch is present, returns its name | |
| 147 | - # - If two or more branches are present, returns the one that has a name | |
| 148 | - # matching root_ref (default_branch or 'master' if default_branch is nil) | |
| 149 | - def discover_default_branch | |
| 150 | - if branch_names.length == 0 | |
| 151 | - nil | |
| 152 | - elsif branch_names.length == 1 | |
| 153 | - branch_names.first | |
| 154 | - else | |
| 155 | - branch_names.select { |v| v == root_ref }.first | |
| 156 | - end | |
| 157 | - end | |
| 158 | - | |
| 159 | - # Archive Project to .tar.gz | |
| 160 | - # | |
| 161 | - # Already packed repo archives stored at | |
| 162 | - # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz | |
| 163 | - # | |
| 164 | - def archive_repo(ref) | |
| 165 | - ref = ref || self.root_ref | |
| 166 | - commit = self.commit(ref) | |
| 167 | - return nil unless commit | |
| 168 | - | |
| 169 | - # Build file path | |
| 170 | - file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz" | |
| 171 | - storage_path = Rails.root.join("tmp", "repositories") | |
| 172 | - file_path = File.join(storage_path, self.path_with_namespace, file_name) | |
| 173 | - | |
| 174 | - # Put files into a directory before archiving | |
| 175 | - prefix = File.basename(self.path_with_namespace) + "/" | |
| 176 | - | |
| 177 | - # Create file if not exists | |
| 178 | - unless File.exists?(file_path) | |
| 179 | - FileUtils.mkdir_p File.dirname(file_path) | |
| 180 | - file = self.repo.archive_to_file(ref, prefix, file_path) | |
| 181 | - end | |
| 182 | - | |
| 183 | - file_path | |
| 184 | - end | |
| 185 | - | |
| 186 | - # Return repo size in megabytes | |
| 187 | - # Cached in redis | |
| 188 | - def size | |
| 189 | - Rails.cache.fetch(cache_key(:size)) do | |
| 190 | - size = popen('du -s', path_to_repo).first.strip.to_i | |
| 191 | - (size.to_f / 1024).round(2) | |
| 192 | - end | |
| 193 | - end | |
| 194 | - | |
| 195 | - def expire_cache | |
| 196 | - Rails.cache.delete(cache_key(:size)) | |
| 197 | - end | |
| 198 | - | |
| 199 | - def cache_key(type) | |
| 200 | - "#{type}:#{path_with_namespace}" | |
| 201 | - end | |
| 202 | - | |
| 203 | - def diffs_between(source_branch, target_branch) | |
| 204 | - # Only show what is new in the source branch compared to the target branch, not the other way around. | |
| 205 | - # The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2) | |
| 206 | - # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B" | |
| 207 | - common_commit = repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip | |
| 208 | - repo.diff(common_commit, source_branch).map { |diff| Gitlab::Git::Diff.new(diff) } | |
| 209 | - | |
| 210 | - rescue Grit::Git::GitTimeout | |
| 211 | - [Gitlab::Git::Diff::BROKEN_DIFF] | |
| 212 | - end | |
| 213 | - | |
| 214 | - protected | |
| 215 | - | |
| 216 | - def decorate_commit(commit, ref = nil) | |
| 217 | - Gitlab::Git::Commit.new(commit, ref) | |
| 218 | - end | |
| 219 | - end | |
| 220 | - end | |
| 221 | -end |
lib/gitlab/git/stats.rb
| ... | ... | @@ -1,75 +0,0 @@ |
| 1 | -module Gitlab | |
| 2 | - module Git | |
| 3 | - class Stats | |
| 4 | - attr_accessor :repo, :ref | |
| 5 | - | |
| 6 | - def initialize repo, ref | |
| 7 | - @repo, @ref = repo, ref | |
| 8 | - end | |
| 9 | - | |
| 10 | - def authors | |
| 11 | - @authors ||= collect_authors | |
| 12 | - end | |
| 13 | - | |
| 14 | - def commits_count | |
| 15 | - @commits_count ||= repo.commit_count(ref) | |
| 16 | - end | |
| 17 | - | |
| 18 | - def files_count | |
| 19 | - args = [ref, '-r', '--name-only' ] | |
| 20 | - repo.git.run(nil, 'ls-tree', nil, {}, args).split("\n").count | |
| 21 | - end | |
| 22 | - | |
| 23 | - def authors_count | |
| 24 | - authors.size | |
| 25 | - end | |
| 26 | - | |
| 27 | - def graph | |
| 28 | - @graph ||= build_graph | |
| 29 | - end | |
| 30 | - | |
| 31 | - protected | |
| 32 | - | |
| 33 | - def collect_authors | |
| 34 | - shortlog = repo.git.shortlog({e: true, s: true }, ref) | |
| 35 | - | |
| 36 | - authors = [] | |
| 37 | - | |
| 38 | - lines = shortlog.split("\n") | |
| 39 | - | |
| 40 | - lines.each do |line| | |
| 41 | - data = line.split("\t") | |
| 42 | - commits = data.first | |
| 43 | - author = Grit::Actor.from_string(data.last) | |
| 44 | - | |
| 45 | - authors << OpenStruct.new( | |
| 46 | - name: author.name, | |
| 47 | - email: author.email, | |
| 48 | - commits: commits.to_i | |
| 49 | - ) | |
| 50 | - end | |
| 51 | - | |
| 52 | - authors.sort_by(&:commits).reverse | |
| 53 | - end | |
| 54 | - | |
| 55 | - def build_graph n = 4 | |
| 56 | - from, to = (Date.today - n.weeks), Date.today | |
| 57 | - args = ['--all', "--since=#{from.to_s(:date)}", '--format=%ad' ] | |
| 58 | - rev_list = repo.git.run(nil, 'rev-list', nil, {}, args).split("\n") | |
| 59 | - | |
| 60 | - commits_dates = rev_list.values_at(* rev_list.each_index.select {|i| i.odd?}) | |
| 61 | - commits_dates = commits_dates.map { |date_str| Time.parse(date_str).to_date.to_s(:date) } | |
| 62 | - | |
| 63 | - commits_per_day = from.upto(to).map do |day| | |
| 64 | - commits_dates.count(day.to_date.to_s(:date)) | |
| 65 | - end | |
| 66 | - | |
| 67 | - OpenStruct.new( | |
| 68 | - labels: from.upto(to).map { |day| day.stamp('Aug 23') }, | |
| 69 | - commits: commits_per_day, | |
| 70 | - weeks: n | |
| 71 | - ) | |
| 72 | - end | |
| 73 | - end | |
| 74 | - end | |
| 75 | -end |
lib/gitlab/git/tree.rb
| ... | ... | @@ -1,52 +0,0 @@ |
| 1 | -module Gitlab | |
| 2 | - module Git | |
| 3 | - class Tree | |
| 4 | - attr_accessor :repository, :sha, :path, :ref, :raw_tree, :id | |
| 5 | - | |
| 6 | - def initialize(repository, sha, ref = nil, path = nil) | |
| 7 | - @repository, @sha, @ref, @path = repository, sha, ref, path | |
| 8 | - | |
| 9 | - @path = nil if @path.blank? | |
| 10 | - | |
| 11 | - # Load tree from repository | |
| 12 | - @commit = @repository.commit(@sha) | |
| 13 | - @raw_tree = @repository.tree(@commit, @path) | |
| 14 | - end | |
| 15 | - | |
| 16 | - def exists? | |
| 17 | - raw_tree | |
| 18 | - end | |
| 19 | - | |
| 20 | - def empty? | |
| 21 | - data.blank? | |
| 22 | - end | |
| 23 | - | |
| 24 | - def trees | |
| 25 | - entries.select { |t| t.is_a?(Grit::Tree) } | |
| 26 | - end | |
| 27 | - | |
| 28 | - def blobs | |
| 29 | - entries.select { |t| t.is_a?(Grit::Blob) } | |
| 30 | - end | |
| 31 | - | |
| 32 | - def is_blob? | |
| 33 | - raw_tree.is_a?(Grit::Blob) | |
| 34 | - end | |
| 35 | - | |
| 36 | - def up_dir? | |
| 37 | - path.present? | |
| 38 | - end | |
| 39 | - | |
| 40 | - def readme | |
| 41 | - @readme ||= blobs.find { |c| c.name =~ /^readme/i } | |
| 42 | - end | |
| 43 | - | |
| 44 | - protected | |
| 45 | - | |
| 46 | - def entries | |
| 47 | - raw_tree.contents | |
| 48 | - end | |
| 49 | - end | |
| 50 | - end | |
| 51 | -end | |
| 52 | - |
spec/lib/gitlab/git/commit_spec.rb
| ... | ... | @@ -1,40 +0,0 @@ |
| 1 | -require "spec_helper" | |
| 2 | - | |
| 3 | -describe Gitlab::Git::Commit do | |
| 4 | - let(:commit) { create(:project_with_code).repository.commit } | |
| 5 | - | |
| 6 | - describe "Commit info" do | |
| 7 | - before do | |
| 8 | - @committer = double( | |
| 9 | - email: 'mike@smith.com', | |
| 10 | - name: 'Mike Smith' | |
| 11 | - ) | |
| 12 | - | |
| 13 | - @author = double( | |
| 14 | - email: 'john@smith.com', | |
| 15 | - name: 'John Smith' | |
| 16 | - ) | |
| 17 | - | |
| 18 | - @raw_commit = double( | |
| 19 | - id: "bcf03b5de6abcf03b5de6c", | |
| 20 | - author: @author, | |
| 21 | - committer: @committer, | |
| 22 | - committed_date: Date.yesterday, | |
| 23 | - authored_date: Date.yesterday, | |
| 24 | - parents: [], | |
| 25 | - message: 'Refactoring specs' | |
| 26 | - ) | |
| 27 | - | |
| 28 | - @commit = Gitlab::Git::Commit.new(@raw_commit) | |
| 29 | - end | |
| 30 | - | |
| 31 | - it { @commit.short_id.should == "bcf03b5de6a" } | |
| 32 | - it { @commit.safe_message.should == @raw_commit.message } | |
| 33 | - it { @commit.created_at.should == @raw_commit.committed_date } | |
| 34 | - it { @commit.author_email.should == @author.email } | |
| 35 | - it { @commit.author_name.should == @author.name } | |
| 36 | - it { @commit.committer_name.should == @committer.name } | |
| 37 | - it { @commit.committer_email.should == @committer.email } | |
| 38 | - it { @commit.different_committer?.should be_true } | |
| 39 | - end | |
| 40 | -end |
spec/lib/gitlab/git/diff_spec.rb
| ... | ... | @@ -1,34 +0,0 @@ |
| 1 | -require "spec_helper" | |
| 2 | - | |
| 3 | -describe Gitlab::Git::Diff do | |
| 4 | - before do | |
| 5 | - @raw_diff_hash = { | |
| 6 | - diff: 'Hello world', | |
| 7 | - new_path: 'temp.rb', | |
| 8 | - old_path: 'test.rb', | |
| 9 | - a_mode: '100644', | |
| 10 | - b_mode: '100644', | |
| 11 | - new_file: false, | |
| 12 | - renamed_file: true, | |
| 13 | - deleted_file: false, | |
| 14 | - } | |
| 15 | - | |
| 16 | - @grit_diff = double('Grit::Diff', @raw_diff_hash) | |
| 17 | - end | |
| 18 | - | |
| 19 | - context 'init from grit' do | |
| 20 | - before do | |
| 21 | - @diff = Gitlab::Git::Diff.new(@raw_diff_hash) | |
| 22 | - end | |
| 23 | - | |
| 24 | - it { @diff.to_hash.should == @raw_diff_hash } | |
| 25 | - end | |
| 26 | - | |
| 27 | - context 'init from hash' do | |
| 28 | - before do | |
| 29 | - @diff = Gitlab::Git::Diff.new(@grit_diff) | |
| 30 | - end | |
| 31 | - | |
| 32 | - it { @diff.to_hash.should == @raw_diff_hash } | |
| 33 | - end | |
| 34 | -end |
spec/lib/gitlab/git/repository_spec.rb
| ... | ... | @@ -1,123 +0,0 @@ |
| 1 | -require "spec_helper" | |
| 2 | - | |
| 3 | -describe Gitlab::Git::Repository do | |
| 4 | - let(:repository) { Gitlab::Git::Repository.new('gitlabhq', 'master') } | |
| 5 | - | |
| 6 | - describe "Respond to" do | |
| 7 | - subject { repository } | |
| 8 | - | |
| 9 | - it { should respond_to(:repo) } | |
| 10 | - it { should respond_to(:tree) } | |
| 11 | - it { should respond_to(:root_ref) } | |
| 12 | - it { should respond_to(:tags) } | |
| 13 | - it { should respond_to(:commit) } | |
| 14 | - it { should respond_to(:commits) } | |
| 15 | - it { should respond_to(:commits_between) } | |
| 16 | - it { should respond_to(:commits_with_refs) } | |
| 17 | - end | |
| 18 | - | |
| 19 | - | |
| 20 | - describe "#discover_default_branch" do | |
| 21 | - let(:master) { 'master' } | |
| 22 | - let(:stable) { 'stable' } | |
| 23 | - | |
| 24 | - it "returns 'master' when master exists" do | |
| 25 | - repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | |
| 26 | - repository.discover_default_branch.should == 'master' | |
| 27 | - end | |
| 28 | - | |
| 29 | - it "returns non-master when master exists but default branch is set to something else" do | |
| 30 | - repository.root_ref = 'stable' | |
| 31 | - repository.should_receive(:branch_names).at_least(:once).and_return([stable, master]) | |
| 32 | - repository.discover_default_branch.should == 'stable' | |
| 33 | - end | |
| 34 | - | |
| 35 | - it "returns a non-master branch when only one exists" do | |
| 36 | - repository.should_receive(:branch_names).at_least(:once).and_return([stable]) | |
| 37 | - repository.discover_default_branch.should == 'stable' | |
| 38 | - end | |
| 39 | - | |
| 40 | - it "returns nil when no branch exists" do | |
| 41 | - repository.should_receive(:branch_names).at_least(:once).and_return([]) | |
| 42 | - repository.discover_default_branch.should be_nil | |
| 43 | - end | |
| 44 | - end | |
| 45 | - | |
| 46 | - describe :commit do | |
| 47 | - it "should return first head commit if without params" do | |
| 48 | - repository.commit.id.should == repository.repo.commits.first.id | |
| 49 | - end | |
| 50 | - | |
| 51 | - it "should return valid commit" do | |
| 52 | - repository.commit(ValidCommit::ID).should be_valid_commit | |
| 53 | - end | |
| 54 | - | |
| 55 | - it "should return nil" do | |
| 56 | - repository.commit("+123_4532530XYZ").should be_nil | |
| 57 | - end | |
| 58 | - end | |
| 59 | - | |
| 60 | - describe :tree do | |
| 61 | - before do | |
| 62 | - @commit = repository.commit(ValidCommit::ID) | |
| 63 | - end | |
| 64 | - | |
| 65 | - it "should raise error w/o arguments" do | |
| 66 | - lambda { repository.tree }.should raise_error | |
| 67 | - end | |
| 68 | - | |
| 69 | - it "should return root tree for commit" do | |
| 70 | - tree = repository.tree(@commit) | |
| 71 | - tree.contents.size.should == ValidCommit::FILES_COUNT | |
| 72 | - tree.contents.map(&:name).should == ValidCommit::FILES | |
| 73 | - end | |
| 74 | - | |
| 75 | - it "should return root tree for commit with correct path" do | |
| 76 | - tree = repository.tree(@commit, ValidCommit::C_FILE_PATH) | |
| 77 | - tree.contents.map(&:name).should == ValidCommit::C_FILES | |
| 78 | - end | |
| 79 | - | |
| 80 | - it "should return root tree for commit with incorrect path" do | |
| 81 | - repository.tree(@commit, "invalid_path").should be_nil | |
| 82 | - end | |
| 83 | - end | |
| 84 | - | |
| 85 | - describe "commits" do | |
| 86 | - subject do | |
| 87 | - commits = repository.commits('master', 'app', 3, 1) | |
| 88 | - commits.map { |c| c.id } | |
| 89 | - end | |
| 90 | - | |
| 91 | - it { should have(3).elements } | |
| 92 | - it { should include("8716fc78f3c65bbf7bcf7b574febd583bc5d2812") } | |
| 93 | - it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } | |
| 94 | - end | |
| 95 | - | |
| 96 | - describe "commits_between" do | |
| 97 | - subject do | |
| 98 | - commits = repository.commits_between("3a4b4fb4cde7809f033822a171b9feae19d41fff", | |
| 99 | - "8470d70da67355c9c009e4401746b1d5410af2e3") | |
| 100 | - commits.map { |c| c.id } | |
| 101 | - end | |
| 102 | - | |
| 103 | - it { should have(3).elements } | |
| 104 | - it { should include("f0f14c8eaba69ebddd766498a9d0b0e79becd633") } | |
| 105 | - it { should_not include("bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a") } | |
| 106 | - end | |
| 107 | - | |
| 108 | - describe "branch names" do | |
| 109 | - subject { repository.branch_names } | |
| 110 | - | |
| 111 | - it { should have(32).elements } | |
| 112 | - it { should include("master") } | |
| 113 | - it { should_not include("branch-from-space") } | |
| 114 | - end | |
| 115 | - | |
| 116 | - describe "tag names" do | |
| 117 | - subject { repository.tag_names } | |
| 118 | - | |
| 119 | - it { should have(16).elements } | |
| 120 | - it { should include("v1.2.0") } | |
| 121 | - it { should_not include("v5.0.0") } | |
| 122 | - end | |
| 123 | -end |
spec/lib/gitlab/git/stats_spec.rb
| ... | ... | @@ -1,28 +0,0 @@ |
| 1 | -require "spec_helper" | |
| 2 | - | |
| 3 | -describe Gitlab::Git::Stats do | |
| 4 | - let(:repository) { Gitlab::Git::Repository.new('gitlabhq', 'master') } | |
| 5 | - | |
| 6 | - before do | |
| 7 | - @stats = Gitlab::Git::Stats.new(repository.raw, 'master') | |
| 8 | - end | |
| 9 | - | |
| 10 | - describe :authors do | |
| 11 | - let(:author) { @stats.authors.first } | |
| 12 | - | |
| 13 | - it { author.name.should == 'Dmitriy Zaporozhets' } | |
| 14 | - it { author.email.should == 'dmitriy.zaporozhets@gmail.com' } | |
| 15 | - it { author.commits.should == 254 } | |
| 16 | - end | |
| 17 | - | |
| 18 | - describe :graph do | |
| 19 | - let(:graph) { @stats.graph } | |
| 20 | - | |
| 21 | - it { graph.labels.should include Date.today.stamp('Aug 23') } | |
| 22 | - it { graph.commits.should be_kind_of(Array) } | |
| 23 | - it { graph.weeks.should == 4 } | |
| 24 | - end | |
| 25 | - | |
| 26 | - it { @stats.commits_count.should == 918 } | |
| 27 | - it { @stats.files_count.should == 550 } | |
| 28 | -end |
spec/support/test_env.rb
| ... | ... | @@ -32,6 +32,7 @@ module TestEnv |
| 32 | 32 | # Use tmp dir for FS manipulations |
| 33 | 33 | repos_path = Rails.root.join('tmp', 'test-git-base-path') |
| 34 | 34 | Gitlab.config.gitlab_shell.stub(repos_path: repos_path) |
| 35 | + Gitlab::Git::Repository.stub(repos_path: repos_path) | |
| 35 | 36 | |
| 36 | 37 | GollumWiki.any_instance.stub(:init_repo) do |path| |
| 37 | 38 | create_temp_repo(File.join(repos_path, "#{path}.git")) | ... | ... |