зеркало из https://github.com/github/grit.git
further file system abstractions
This commit is contained in:
Родитель
82cac1a88e
Коммит
4e694b9a37
121
lib/grit/git.rb
121
lib/grit/git.rb
|
@ -1,3 +1,4 @@
|
|||
require 'tempfile'
|
||||
module Grit
|
||||
|
||||
class Git
|
||||
|
@ -13,7 +14,11 @@ module Grit
|
|||
undef_method :clone
|
||||
|
||||
include GitRuby
|
||||
|
||||
|
||||
def exist?
|
||||
File.exist?(self.git_dir)
|
||||
end
|
||||
|
||||
def put_raw_object(content, type)
|
||||
ruby_git.put_raw_object(content, type)
|
||||
end
|
||||
|
@ -49,6 +54,14 @@ module Grit
|
|||
end
|
||||
alias_method :e, :shell_escape
|
||||
|
||||
# Check if a normal file exists on the filesystem
|
||||
# +file+ is the relative path from the Git dir
|
||||
#
|
||||
# Returns Boolean
|
||||
def fs_exist?(file)
|
||||
File.exist?(File.join(self.git_dir, file))
|
||||
end
|
||||
|
||||
# Read a normal file from the filesystem.
|
||||
# +file+ is the relative path from the Git dir
|
||||
#
|
||||
|
@ -75,9 +88,113 @@ module Grit
|
|||
#
|
||||
# Returns nothing
|
||||
def fs_delete(file)
|
||||
FileUtils.rm_f(File.join(self.git_dir,file))
|
||||
FileUtils.rm_rf(File.join(self.git_dir, file))
|
||||
end
|
||||
|
||||
# Move a normal file
|
||||
# +from+ is the relative path to the current file
|
||||
# +to+ is the relative path to the destination file
|
||||
#
|
||||
# Returns nothing
|
||||
def fs_move(from, to)
|
||||
FileUtils.mv(File.join(self.git_dir, from), File.join(self.git_dir, to))
|
||||
end
|
||||
|
||||
# Make a directory
|
||||
# +dir+ is the relative path to the directory to create
|
||||
#
|
||||
# Returns nothing
|
||||
def fs_mkdir(dir)
|
||||
FileUtils.mkdir_p(File.join(self.git_dir, dir))
|
||||
end
|
||||
|
||||
# Chmod the the file or dir and everything beneath
|
||||
# +file+ is the relative path from the Git dir
|
||||
#
|
||||
# Returns nothing
|
||||
def fs_chmod(mode, file = '/')
|
||||
FileUtils.chmod_R(mode, File.join(self.git_dir, file))
|
||||
end
|
||||
|
||||
# Create a new directory
|
||||
# +path+ is an absolute path
|
||||
#
|
||||
# Returns nothing
|
||||
def fs_mkdir(path)
|
||||
FileUtils.mkdir_p(path)
|
||||
end
|
||||
|
||||
def fs_exist(path)
|
||||
File.exist?(path)
|
||||
end
|
||||
|
||||
def list_remotes
|
||||
remotes = []
|
||||
Dir.chdir(File.join(self.git_dir, 'refs/remotes')) do
|
||||
remotes = Dir.glob('*')
|
||||
end
|
||||
remotes
|
||||
rescue
|
||||
[]
|
||||
end
|
||||
|
||||
def create_tempfile(seed, unlink = false)
|
||||
path = Tempfile.new(seed).path
|
||||
File.unlink(path) if unlink
|
||||
return path
|
||||
end
|
||||
|
||||
def check_applies(head_sha, applies_sha)
|
||||
git_index = create_tempfile('index', true)
|
||||
(o1, exit1) = raw_git("git read-tree #{head_sha} 2>/dev/null", git_index)
|
||||
(o2, exit2) = raw_git("git diff #{applies_sha}^ #{applies_sha} | git apply --check --cached >/dev/null 2>/dev/null", git_index)
|
||||
return (exit1 + exit2)
|
||||
end
|
||||
|
||||
def get_patch(applies_sha)
|
||||
git_index = create_tempfile('index', true)
|
||||
(patch, exit2) = raw_git("git diff #{applies_sha}^ #{applies_sha}", git_index)
|
||||
patch
|
||||
end
|
||||
|
||||
def apply_patch(head_sha, patch)
|
||||
git_index = create_tempfile('index', true)
|
||||
|
||||
git_patch = create_tempfile('patch')
|
||||
File.open(git_patch, 'w+') { |f| f.print patch }
|
||||
|
||||
raw_git("git read-tree #{head_sha} 2>/dev/null", git_index)
|
||||
(op, exit) = raw_git("git apply --cached < #{git_patch}", git_index)
|
||||
if exit == 0
|
||||
return raw_git("git write-tree", git_index).first.chomp
|
||||
end
|
||||
false
|
||||
end
|
||||
|
||||
# RAW CALLS WITH ENV SETTINGS
|
||||
def raw_git_call(command, index)
|
||||
tmp = ENV['GIT_INDEX_FILE']
|
||||
ENV['GIT_INDEX_FILE'] = index
|
||||
out = `#{command}`
|
||||
after = ENV['GIT_INDEX_FILE'] # someone fucking with us ??
|
||||
ENV['GIT_INDEX_FILE'] = tmp
|
||||
if after != index
|
||||
raise 'environment was changed for the git call'
|
||||
end
|
||||
[out, $?.exitstatus]
|
||||
end
|
||||
|
||||
def raw_git(command, index)
|
||||
output = nil
|
||||
Dir.chdir(self.git_dir) do
|
||||
output = raw_git_call(command, index)
|
||||
end
|
||||
output
|
||||
end
|
||||
# RAW CALLS WITH ENV SETTINGS END
|
||||
|
||||
|
||||
|
||||
# Run the given git command with the specified arguments and return
|
||||
# the result as a String
|
||||
# +cmd+ is the command
|
||||
|
|
|
@ -139,6 +139,34 @@ module Grit
|
|||
def remotes
|
||||
Remote.find_all(self)
|
||||
end
|
||||
|
||||
def remote_list
|
||||
self.git.list_remotes
|
||||
end
|
||||
|
||||
def remote_add(name, url)
|
||||
self.git.remote({}, 'add', name, url)
|
||||
end
|
||||
|
||||
def remote_fetch(name)
|
||||
self.git.fetch({}, name)
|
||||
end
|
||||
|
||||
# takes an array of remote names and last pushed dates
|
||||
# fetches from all of the remotes where the local fetch
|
||||
# date is earlier than the passed date, then records the
|
||||
# last fetched date
|
||||
#
|
||||
# { 'origin' => date,
|
||||
# 'peter => date,
|
||||
# }
|
||||
def remotes_fetch_needed(remotes)
|
||||
remotes.each do |remote, date|
|
||||
# TODO: check against date
|
||||
self.remote_fetch(remote)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# An array of Ref objects representing the refs in
|
||||
# this repo
|
||||
|
@ -280,9 +308,19 @@ module Grit
|
|||
# Returns Grit::Repo (the newly created repo)
|
||||
def self.init_bare(path, git_options = {}, repo_options = {})
|
||||
git = Git.new(path)
|
||||
git.fs_mkdir('..')
|
||||
git.init(git_options)
|
||||
self.new(path, repo_options)
|
||||
end
|
||||
|
||||
def self.init_bare_or_open(path, git_options = {}, repo_options = {})
|
||||
git = Git.new(path)
|
||||
if !git.exist?
|
||||
git.fs_mkdir(path)
|
||||
git.init(git_options)
|
||||
end
|
||||
self.new(path, repo_options)
|
||||
end
|
||||
|
||||
# Fork a bare git repository from this repo
|
||||
# +path+ is the full path of the new repo (traditionally ends with /<name>.git)
|
||||
|
@ -292,6 +330,7 @@ module Grit
|
|||
def fork_bare(path, options = {})
|
||||
default_options = {:bare => true, :shared => true}
|
||||
real_options = default_options.merge(options)
|
||||
Git.new(path).fs_mkdir('..')
|
||||
self.git.clone(real_options, self.path, path)
|
||||
Repo.new(path)
|
||||
end
|
||||
|
@ -335,7 +374,7 @@ module Grit
|
|||
def archive_tar_gz(treeish = 'master', prefix = nil)
|
||||
options = {}
|
||||
options[:prefix] = prefix if prefix
|
||||
self.git.archive(options, treeish, "| gzip")
|
||||
self.git.archive(options, treeish, "| gzip -n")
|
||||
end
|
||||
|
||||
# Write an archive directly to a file
|
||||
|
@ -377,10 +416,9 @@ module Grit
|
|||
#
|
||||
# Returns Array[String] (pathnames of alternates)
|
||||
def alternates
|
||||
alternates_path = File.join(self.path, *%w{objects info alternates})
|
||||
|
||||
if File.exist?(alternates_path)
|
||||
File.read(alternates_path).strip.split("\n")
|
||||
alternates_path = "objects/info/alternates"
|
||||
if self.git.fs_exist?(alternates_path)
|
||||
self.git.fs_read(alternates_path).strip.split("\n")
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
@ -418,6 +456,18 @@ module Grit
|
|||
commit_sha
|
||||
end
|
||||
|
||||
# Rename the current repository directory.
|
||||
# +name+ is the new name
|
||||
#
|
||||
# Returns nothing
|
||||
def rename(name)
|
||||
if @bare
|
||||
self.git.fs_move('/', "../#{name}")
|
||||
else
|
||||
self.git.fs_move('/', "../../#{name}")
|
||||
end
|
||||
end
|
||||
|
||||
# Pretty object inspection
|
||||
def inspect
|
||||
%Q{#<Grit::Repo "#{@path}">}
|
||||
|
|
|
@ -99,7 +99,7 @@ class TestGit < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_fs_delete
|
||||
FileUtils.expects(:rm_f).with(File.join(@git.git_dir, 'foo'))
|
||||
FileUtils.expects(:rm_rf).with(File.join(@git.git_dir, 'foo'))
|
||||
@git.fs_delete('foo')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -242,7 +242,7 @@ class TestRepo < Test::Unit::TestCase
|
|||
# disable_daemon_serve
|
||||
|
||||
def test_disable_daemon_serve
|
||||
FileUtils.expects(:rm_f).with(File.join(@r.path, 'git-daemon-export-ok'))
|
||||
FileUtils.expects(:rm_rf).with(File.join(@r.path, 'git-daemon-export-ok'))
|
||||
@r.disable_daemon_serve
|
||||
end
|
||||
|
||||
|
@ -255,7 +255,7 @@ class TestRepo < Test::Unit::TestCase
|
|||
|
||||
def test_alternates_with_two_alternates
|
||||
File.expects(:exist?).with("#{absolute_project_path}/.git/objects/info/alternates").returns(true)
|
||||
File.expects(:read).returns("/path/to/repo1/.git/objects\n/path/to/repo2.git/objects\n")
|
||||
File.any_instance.expects(:read).returns("/path/to/repo1/.git/objects\n/path/to/repo2.git/objects\n")
|
||||
|
||||
assert_equal ["/path/to/repo1/.git/objects", "/path/to/repo2.git/objects"], @r.alternates
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче