diff options
author | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2013-03-31 18:49:06 +0300 |
---|---|---|
committer | Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> | 2013-03-31 18:49:06 +0300 |
commit | 676bce2ab941fcc50ef5796ff77229e238eb9b35 (patch) | |
tree | b1da10d5d04990ddef5a69f83c3a2b8f8779b49b /lib/gitlab/git/repository.rb | |
parent | 71b0f8ea0b7d4460fdbb70ca9b61789d37ed4885 (diff) | |
download | gitlab-ce-676bce2ab941fcc50ef5796ff77229e238eb9b35.tar.gz |
Move Commit and Repository logic to lib/gitlab/git
Diffstat (limited to 'lib/gitlab/git/repository.rb')
-rw-r--r-- | lib/gitlab/git/repository.rb | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb new file mode 100644 index 00000000000..53d9c735787 --- /dev/null +++ b/lib/gitlab/git/repository.rb @@ -0,0 +1,181 @@ +# Gitlab::Git::Gitlab::Git::Commit is a wrapper around native Grit::Repository object +# We dont want to use grit objects inside app/ +# It helps us easily migrate to rugged in future +module Gitlab + module Git + class Repository + include Gitlab::Popen + + class NoRepository < StandardError; end + + # Repository directory name with namespace direcotry + # Examples: + # gitlab/gitolite + # diaspora + # + attr_accessor :path_with_namespace + + # Grit repo object + attr_accessor :repo + + # Default branch in the repository + attr_accessor :root_ref + + 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 + + def raw + repo + end + + def path_to_repo + @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git") + end + + def repo + @repo ||= Grit::Repo.new(path_to_repo) + rescue Grit::NoSuchPathError + raise NoRepository.new('no repository for such path') + end + + def commit(commit_id = nil) + Gitlab::Git::Commit.find_or_first(repo, commit_id, root_ref) + end + + def fresh_commits(n = 10) + Gitlab::Git::Commit.fresh_commits(repo, n) + end + + def commits_with_refs(n = 20) + Gitlab::Git::Commit.commits_with_refs(repo, n) + end + + def commits_since(date) + Gitlab::Git::Commit.commits_since(repo, date) + end + + def commits(ref, path = nil, limit = nil, offset = nil) + Gitlab::Git::Commit.commits(repo, ref, path, limit, offset) + end + + def last_commit_for(ref, path = nil) + commits(ref, path, 1).first + end + + def commits_between(from, to) + Gitlab::Git::Commit.commits_between(repo, from, to) + end + + # Returns an Array of branch names + # sorted by name ASC + def branch_names + branches.map(&:name) + end + + # Returns an Array of Branches + def branches + repo.branches.sort_by(&:name) + end + + # Returns an Array of tag names + def tag_names + repo.tags.collect(&:name).sort.reverse + end + + # Returns an Array of Tags + def tags + repo.tags.sort_by(&:name).reverse + end + + # Returns an Array of branch and tag names + def ref_names + [branch_names + tag_names].flatten + end + + def heads + @heads ||= repo.heads + end + + def tree(fcommit, path = nil) + fcommit = commit if fcommit == :head + tree = fcommit.tree + path ? (tree / path) : tree + end + + def has_commits? + !!commit + rescue Grit::NoSuchPathError + false + end + + def empty? + !has_commits? + end + + # 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) + 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 + + # Archive Project to .tar.gz + # + # Already packed repo archives stored at + # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz + # + 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 + + # Return repo size in megabytes + # Cached in redis + 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 + + def expire_cache + Rails.cache.delete(cache_key(:size)) + end + + def cache_key(type) + "#{type}:#{path_with_namespace}" + end + end + end +end |