Class: Gitlab::Git::Repository

Inherits:
Object
  • Object
show all
Includes:
Popen
Defined in:
lib/gitlab_git/repository.rb

Defined Under Namespace

Classes: NoRepository

Class Attribute Summary collapse

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Popen

#popen

Constructor Details

#initialize(path_with_namespace, root_ref = 'master') ⇒ Repository

Returns a new instance of Repository.



28
29
30
31
32
33
34
# File 'lib/gitlab_git/repository.rb', line 28

def initialize(path_with_namespace, root_ref = 'master')
  @root_ref = root_ref || "master"
  @path_with_namespace = path_with_namespace

  # Init grit repo object
  repo
end

Class Attribute Details

.repos_pathObject

Returns the value of attribute repos_path.



12
13
14
# File 'lib/gitlab_git/repository.rb', line 12

def repos_path
  @repos_path
end

Instance Attribute Details

#path_with_namespaceObject

Repository directory name with namespace direcotry Examples:

gitlab/gitolite
diaspora


20
21
22
# File 'lib/gitlab_git/repository.rb', line 20

def path_with_namespace
  @path_with_namespace
end

#repoObject

Grit repo object



23
24
25
# File 'lib/gitlab_git/repository.rb', line 23

def repo
  @repo
end

#root_refObject

Default branch in the repository



26
27
28
# File 'lib/gitlab_git/repository.rb', line 26

def root_ref
  @root_ref
end

Instance Method Details

#archive_repo(ref) ⇒ Object

Archive Project to .tar.gz

Already packed repo archives stored at app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/gitlab_git/repository.rb', line 168

def archive_repo(ref)
  ref = ref || self.root_ref
  commit = self.commit(ref)
  return nil unless commit

  # Build file path
  file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz"
  storage_path = Rails.root.join("tmp", "repositories")
  file_path = File.join(storage_path, self.path_with_namespace, file_name)

  # Put files into a directory before archiving
  prefix = File.basename(self.path_with_namespace) + "/"

  # Create file if not exists
  unless File.exists?(file_path)
    FileUtils.mkdir_p File.dirname(file_path)
    file = self.repo.archive_to_file(ref, prefix,  file_path)
  end

  file_path
end

#branch_namesObject

Returns an Array of branch names sorted by name ASC



103
104
105
# File 'lib/gitlab_git/repository.rb', line 103

def branch_names
  branches.map(&:name)
end

#branchesObject

Returns an Array of Branches



108
109
110
# File 'lib/gitlab_git/repository.rb', line 108

def branches
  repo.branches.sort_by(&:name)
end

#cache_key(type) ⇒ Object



203
204
205
# File 'lib/gitlab_git/repository.rb', line 203

def cache_key(type)
  "#{type}:#{path_with_namespace}"
end

#commit(commit_id = nil) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/gitlab_git/repository.rb', line 54

def commit(commit_id = nil)
  commit = if commit_id
             # Find repo.refs first,
             # because if commit_id is "tag name",
             # repo.commit(commit_id) returns wrong commit sha
             # that is git tag object sha.
             ref = repo.refs.find {|r| r.name == commit_id}
             if ref
               ref.commit
             else
               repo.commit(commit_id)
             end
           else
             repo.commits(root_ref).first
           end

  decorate_commit(commit) if commit
end

#commits(ref, path = nil, limit = nil, offset = nil) ⇒ Object



83
84
85
86
87
88
89
90
91
# File 'lib/gitlab_git/repository.rb', line 83

def commits(ref, path = nil, limit = nil, offset = nil)
  if path && path != ''
    repo.log(ref, path, max_count: limit, skip: offset, follow: true)
  elsif limit && offset
    repo.commits(ref, limit.to_i, offset.to_i)
  else
    repo.commits(ref)
  end.map{ |c| decorate_commit(c) }
end

#commits_between(from, to) ⇒ Object



93
94
95
# File 'lib/gitlab_git/repository.rb', line 93

def commits_between(from, to)
  repo.commits_between(from, to).map { |c| decorate_commit(c) }
end

#commits_with_refs(n = 20) ⇒ Object



73
74
75
76
77
78
79
80
81
# File 'lib/gitlab_git/repository.rb', line 73

def commits_with_refs(n = 20)
  commits = repo.branches.map { |ref| decorate_commit(ref.commit, ref) }

  commits.sort! do |x, y|
    y.committed_date <=> x.committed_date
  end

  commits[0..n]
end

#diffs_between(source_branch, target_branch) ⇒ Object



207
208
209
210
211
212
213
214
215
216
# File 'lib/gitlab_git/repository.rb', line 207

def diffs_between(source_branch, target_branch)
  # Only show what is new in the source branch compared to the target branch, not the other way around.
  # The linex below with merge_base is equivalent to diff with three dots (git diff branch1...branch2)
  # From the git documentation: "git diff A...B" is equivalent to "git diff $(git-merge-base A B) B"
  common_commit = repo.git.native(:merge_base, {}, [target_branch, source_branch]).strip
  repo.diff(common_commit, source_branch).map { |diff| Gitlab::Git::Diff.new(diff) }

rescue Grit::Git::GitTimeout
  [Gitlab::Git::Diff::BROKEN_DIFF]
end

#discover_default_branchObject

Discovers the default branch based on the repository’s available branches

  • If no branches are present, returns nil

  • If one branch is present, returns its name

  • If two or more branches are present, returns the one that has a name matching root_ref (default_branch or ‘master’ if default_branch is nil)



153
154
155
156
157
158
159
160
161
# File 'lib/gitlab_git/repository.rb', line 153

def discover_default_branch
  if branch_names.length == 0
    nil
  elsif branch_names.length == 1
    branch_names.first
  else
    branch_names.select { |v| v == root_ref }.first
  end
end

#empty?Boolean

Returns:

  • (Boolean)


143
144
145
# File 'lib/gitlab_git/repository.rb', line 143

def empty?
  !has_commits?
end

#expire_cacheObject



199
200
201
# File 'lib/gitlab_git/repository.rb', line 199

def expire_cache
  Rails.cache.delete(cache_key(:size))
end

#has_commits?Boolean

Returns:

  • (Boolean)


137
138
139
140
141
# File 'lib/gitlab_git/repository.rb', line 137

def has_commits?
  !!commit
rescue Grit::NoSuchPathError
  false
end

#headsObject



127
128
129
# File 'lib/gitlab_git/repository.rb', line 127

def heads
  @heads ||= repo.heads
end

#last_commit_for(ref, path = nil) ⇒ Object



97
98
99
# File 'lib/gitlab_git/repository.rb', line 97

def last_commit_for(ref, path = nil)
  commits(ref, path, 1).first
end

#path_to_repoObject



40
41
42
# File 'lib/gitlab_git/repository.rb', line 40

def path_to_repo
  @path_to_repo ||= File.join(repos_path, "#{path_with_namespace}.git")
end

#rawObject



36
37
38
# File 'lib/gitlab_git/repository.rb', line 36

def raw
  repo
end

#ref_namesObject

Returns an Array of branch and tag names



123
124
125
# File 'lib/gitlab_git/repository.rb', line 123

def ref_names
  [branch_names + tag_names].flatten
end

#repos_pathObject



44
45
46
# File 'lib/gitlab_git/repository.rb', line 44

def repos_path
  self.class.repos_path
end

#sizeObject

Return repo size in megabytes Cached in redis



192
193
194
195
196
197
# File 'lib/gitlab_git/repository.rb', line 192

def size
  Rails.cache.fetch(cache_key(:size)) do
    size = popen('du -s', path_to_repo).first.strip.to_i
    (size.to_f / 1024).round(2)
  end
end

#tag_namesObject

Returns an Array of tag names



113
114
115
# File 'lib/gitlab_git/repository.rb', line 113

def tag_names
  repo.tags.collect(&:name).sort.reverse
end

#tagsObject

Returns an Array of Tags



118
119
120
# File 'lib/gitlab_git/repository.rb', line 118

def tags
  repo.tags.sort_by(&:name).reverse
end

#tree(fcommit, path = nil) ⇒ Object



131
132
133
134
135
# File 'lib/gitlab_git/repository.rb', line 131

def tree(fcommit, path = nil)
  fcommit = commit if fcommit == :head
  tree = fcommit.tree
  path ? (tree / path) : tree
end