GitHub Sale: sign up for any paid plan this week and pay nothing until January 1, 2009!  [ hide ]

public
Rubygem
Description: Piston is a utility that eases vendor branch management. This repository is a complete reimplementation of Piston to provide different backends, depending on the repositories and working copies you pistonize from.
Homepage: http://piston.rubyforge.org/
Clone URL: git://github.com/francois/piston.git
piston / lib / piston / git / commit.rb
100644 103 lines (87 sloc) 3.131 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
require "piston/git/client"
require "piston/revision"
require "fileutils"
 
module Piston
  module Git
    class Commit < Piston::Revision
      class InvalidCommit < RuntimeError; end
      class Gone < InvalidCommit; end
 
      alias_method :commit, :revision
      attr_reader :sha1
 
      def initialize(repository, revision, recalled_values={})
        super
        @revision = 'master' if @revision.upcase == 'HEAD'
      end
 
      def client
        @client ||= Piston::Git::Client.instance
      end
 
      def git(*args)
        client.git(*args)
      end
 
      def recalled_commit_id
        recalled_values[Piston::Git::COMMIT]
      end
 
      def validate!
        begin
          data = git("ls-remote", @repository.url)
          self
        rescue Piston::Git::Client::CommandError
          raise Piston::Git::Commit::Gone, "Repository at #{@repository.url} does not exist anymore"
        end
      end
 
      def name
        commit[0,7]
      end
 
      def branch_name
        "my-#{commit}"
      end
 
      def checkout_to(dir)
        super
        git(:clone, repository.url, @dir)
        Dir.chdir(@dir) do
          git(:checkout, "-b", branch_name, commit)
          response = git(:log, "-n", "1")
          @sha1 = $1 if response =~ /commit\s+([a-f\d]{40})/i
        end
      end
 
      def update_to(commit)
        raise ArgumentError, "Commit #{self.commit} of #{repository.url} was never checked out -- can't update" unless @dir
        
        Dir.chdir(@dir) do
          logger.debug {"Saving old changes before updating"}
          git(:commit, '-a', '-m', 'old changes')
          logger.debug {"Merging old changes with #{commit}"}
          git(:merge, '--squash', commit)
          output = git(:status)
          added = output.scan(/new file:\s+(.*)$/).flatten
          deleted = output.scan(/deleted:\s+(.*)$/).flatten
          renamed = output.scan(/renamed:\s+(.+) -> (.+)$/)
          [added, deleted, renamed]
        end
      end
 
      def remember_values
        # find last commit for +commit+ if it wasn't checked out
        @sha1 = git('ls-remote', repository.url, commit).match(/\w+/)[0] unless @sha1
        # if ls-remote returns nothing, +commit+ must be a commit, not a branch
        @sha1 = commit unless @sha1
        { Piston::Git::COMMIT => @sha1, Piston::Git::BRANCH => commit }
      end
 
      def each
        raise ArgumentError, "Never cloned + checked out" if @dir.nil?
        @dir.find do |path|
          Find.prune if path.to_s =~ %r{/[.]git}
          next if @dir == path
          next if File.directory?(path)
          yield path.relative_path_from(@dir)
        end
      end
 
      def remotely_modified
        branch = recalled_values[Piston::Git::BRANCH]
        logger.debug {"Get last commit in #{branch} of #{repository.url}"}
        commit = git('ls-remote', repository.url, branch).match(/\w+/)
        # when we update to a commit, instead latest commit of a branch, +branch+ will be a commit, and ls-remote can return nil
        commit = commit[0] unless commit.nil?
        commit != self.commit
      end
    end
  end
end