lib/gitrb/repository.rb in gitrb-0.2.3 vs lib/gitrb/repository.rb in gitrb-0.2.4

- old
+ new

@@ -40,12 +40,10 @@ def initialize(options = {}) @bare = options[:bare] || false @branch = options[:branch] || 'master' @logger = options[:logger] || Logger.new(nil) @encoding = options[:encoding] || DEFAULT_ENCODING - @lock = {} - @transaction = Mutex.new @path = options[:path] @path.chomp!('/') @path += '/.git' if !@bare @@ -54,21 +52,27 @@ load_packs load end + def dup + super.instance_eval do + @objects = Trie.new + load + self + end + end + # Bare repository? def bare? @bare end # Switch branch def branch=(branch) - @transaction.synchronize do - @branch = branch - load - end + @branch = branch + load end # Has our repository been changed on disk? def changed? !head || head.id != read_head_id @@ -79,26 +83,19 @@ load if changed? end # Clear cached objects def clear - @transaction.synchronize do - @objects.clear - load - end + @objects.clear + load end - # Is there any transaction going on? - def in_transaction? - !!@lock[Thread.current.object_id] - end - # Difference between versions # Options: # :to - Required target commit # :from - Optional source commit (otherwise comparision with empty tree) - # :path - Restrict to path + # :path - Restrict to path/or paths # :detect_renames - Detect renames O(n^2) # :detect_copies - Detect copies O(n^2), very slow def diff(opts) from, to = opts[:from], opts[:to] if from && !(Commit === from) @@ -110,33 +107,34 @@ to = Reference.new(:repository => self, :id => to) end Diff.new(from, to, git_diff_tree('--root', '--full-index', '-u', opts[:detect_renames] ? '-M' : nil, opts[:detect_copies] ? '-C' : nil, - from ? from.id : nil, to.id, '--', opts[:path])) + from ? from.id : nil, to.id, '--', *opts[:path])) end # All changes made inside a transaction are atomic. If some # exception occurs the transaction will be rolled back. # # Example: # repository.transaction { repository['a'] = 'b' } # def transaction(message = '', author = nil, committer = nil) - @transaction.synchronize do - begin - start_transaction - result = yield - commit(message, author, committer) - result - rescue - rollback_transaction - raise - ensure - finish_transaction - end - end + lock = File.open("#{head_path}.lock", 'w') + lock.flock(File::LOCK_EX) + refresh + + result = yield + commit(message, author, committer) + result + rescue + @objects.clear + load + raise + ensure + lock.close rescue nil + File.unlink("#{head_path}.lock") rescue nil end # Write a commit object to disk and set the head of the current branch. # # Returns the commit object @@ -160,19 +158,23 @@ commit end # Returns a list of commits starting from head commit. + # Options: + # :path - Restrict to path/or paths + # :max_count - Maximum count of commits + # :skip - Skip n commits + # :start - Commit to start from def log(opts = {}) max_count = opts[:max_count] skip = opts[:skip] start = opts[:start] - path = opts[:path] raise ArgumentError, "Invalid commit: #{start}" if start.to_s =~ /^\-/ log = git_log('--pretty=tformat:%H%n%P%n%T%n%an%n%ae%n%at%n%cn%n%ce%n%ct%n%x00%s%n%b%x00', skip ? "--skip=#{skip.to_i}" : nil, - max_count ? "--max-count=#{max_count.to_i}" : nil, start, '--', path).split(/\n*\x00\n*/) + max_count ? "--max-count=#{max_count.to_i}" : nil, start, '--', *opts[:path]).split(/\n*\x00\n*/) commits = [] log.each_slice(2) do |data, message| data = data.split("\n") parents = data[1].empty? ? nil : data[1].split(' ').map {|id| Reference.new(:repository => self, :id => id) } commits << Commit.new(:repository => self, @@ -259,11 +261,11 @@ def put(object) raise ArgumentError unless object && GitObject === object content = object.dump data = "#{object.type} #{content.bytesize rescue content.length}\0#{content}" - id = sha(data) + id = Digest::SHA1.hexdigest(data) path = object_path(id) @logger.debug "gitrb: Storing #{id}" if !File.exists?(path) @@ -346,47 +348,19 @@ else raise ArgumentError, "Not a valid Git repository: '#{@path}'" if !File.directory?("#{@path}/objects") end end - # Start a transaction. - # - # Tries to get lock on lock file, load the this repository if - # has changed in the repository. - def start_transaction - file = File.open("#{head_path}.lock", 'w') - file.flock(File::LOCK_EX) - @lock[Thread.current.object_id] = file - refresh - end - - # Rerepository the state of the repository. - # - # Any changes made to the repository are discarded. - def rollback_transaction - @objects.clear - load - end - - # Finish the transaction. - # - # Release the lock file. - def finish_transaction - @lock[Thread.current.object_id].close rescue nil - @lock.delete(Thread.current.object_id) - File.unlink("#{head_path}.lock") rescue nil - end - def get_type(id, expected) object = get(id) raise NotFound, "Wrong type #{object.type}, expected #{expected}" if object && object.type != expected object end def load_packs @packs = Trie.new - @objects = Util::Synchronized.new(Trie.new) + @objects = Trie.new packs_path = "#{@path}/objects/pack" if File.directory?(packs_path) Dir.open(packs_path) do |dir| entries = dir.select { |entry| entry =~ /\.pack$/i } @@ -406,14 +380,9 @@ else @head = nil @root = Tree.new(:repository => self) end @logger.debug "gitrb: Reloaded, head is #{head ? head.id : 'nil'}" - end - - # Returns the hash value of an object string. - def sha(str) - Digest::SHA1.hexdigest(str)[0, 40] end # Returns the path to the current head file. def head_path "#{path}/refs/heads/#{branch}"