Blob of data/hooks/post-receive (raw blob data)

1 #!/usr/bin/env ruby
2
3 incpath = File.dirname(__FILE__)
4 $: << incpath
5
6 require 'rails_env'
7 require 'date'
8
9 gitdir = File.expand_path(File.join(incpath, ".."))
10 repository = Repository.find_by_path(gitdir)
11
12 if repository.nil?
13 $stderr.puts "Unknown repository"
14 exit 0
15 end
16
17 project = repository.project
18 git = Grit::Git.new(gitdir)
19
20 while line = gets
21 # puts "@@> #{line.inspect}"
22 # 3b480c5c30962c9f5b82a9c61a75992dc605de21 ee27ee3a022802c0569f9cdef6e9ad29aea096a8 refs/heads/master\n
23 oldrev, newrev, revname = line.split(" ")
24 current_rev = newrev
25 newtype = oldtype = current_rev_type = "commit"
26
27 action = :create
28 if oldrev =~ /^0+$/
29 action = :create
30 else
31 if newrev =~ /^0+$/
32 action = :delete
33 else
34 action = :update
35 end
36 end
37
38 if action != :delete
39 newtype = git.cat_file({:t => true}, newrev)
40 end
41
42 if action == :update
43 oldtype = git.cat_file({:t => true}, oldrev)
44 end
45
46 if action == :delete
47 current_rev = oldrev
48 current_rev_type = oldtype
49 end
50
51 # type => heads, tags, remotes
52 # name => branch name
53 path, type, name = revname.split("/")
54 revs = [ current_rev ]
55 emails = [git.show({:pretty => "format:%ce", :s => true}, current_rev)]
56
57 if type == "heads"
58 if action == :update
59 revs = git.rev_list({}, "#{oldrev}..#{newrev}").split("\n")
60 emails = git.log({:pretty => "format:%ce"}, "#{oldrev}..#{newrev}").split("\n")
61 elsif action == :create && name == "master"
62 revs = git.rev_list({}, current_rev).split("\n")
63 emails = git.log({:pretty => "format:%ce"}, current_rev).split("\n")
64 end
65 end
66
67 users = repository.committers.find(:all, :conditions => ["email in (?)", emails])
68 user_map = users.inject({}) { |hash, user| hash[user.email] = user; hash }
69
70 revs.each do |sha1|
71 info = git.show({ :pretty => "format:author: %cn%nemail: %ce%ndate: %ct%nmessage: %s", :s => true}, sha1)
72
73 hash = {}
74 info.each { |line|
75 if line =~ /(\w+):\s(.*)$/
76 key = $1.to_sym
77 value = $2
78
79 value = Time.at(value.to_i).utc if key == :date
80
81 hash[key] = value
82 end
83 }
84
85 # action => create, delete, update
86 # rev_type => commit, tag
87
88 user = user_map[hash[:email]]
89 if user.nil?
90 # TODO: no user should be ok, no need to skip
91 # $stdout.puts "** The email '#{hash[:email]}' is not registered."
92 next
93 end
94
95 action_id = nil
96 ref = nil
97 if current_rev_type == "commit"
98 if type == "heads"
99 case action
100 when :create
101 action_id = Action::CREATE_BRANCH
102 ref = name
103 when :update
104 action_id = Action::COMMIT
105 ref = sha1
106 when :delete
107 action_id = Action::DELETE_BRANCH
108 ref = name
109 end
110 elsif type == "tags"
111 if action == :create
112 action_id = Action::CREATE_TAG
113 ref = name
114 elsif action == :delete
115 action_id = Action::DELETE_TAG
116 ref = name
117 end
118 end
119 elsif current_rev_type == "tag"
120 if type == "tags"
121 if action == :create
122 action_id = Action::CREATE_TAG
123 ref = name
124 elsif action == :delete
125 action_id = Action::DELETE_TAG
126 ref = name
127 end
128 end
129 end
130
131 next unless action_id
132
133 project.create_event(action_id, repository, user, ref, hash[:message], hash[:date])
134 action = :update
135 end
136 end
137
138 puts "[OK]"