public
Description: Gitorious aims to provide a great way of doing distributed opensource code collaboration.
Homepage: http://gitorious.org/projects/gitorious
Clone URL: git://github.com/dysinger/gitorious.git
gitorious / script / rebuild_events
100755 206 lines (178 sloc) 5.782 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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#!/usr/bin/env ruby -KU
 
ENV["PATH"] = "/usr/local/bin/:/opt/local/bin:#{ENV["PATH"]}"
ENV["RAILS_ENV"] ||= "production"
 
require File.dirname(__FILE__) + "/../config/environment"
 
abort("Usage: #{$0} repo_id") unless ARGV[0]
 
$stdout.sync = true
 
def create_repo_creation_events_for(project)
  project.repository_clones.each do |repo|
    puts "creating Repository clone event in #{project.slug}/#{repo.name}"
   project.events.create({
     :action => Action::CLONE_REPOSITORY,
     :target => repo,
     :user => repo.user,
     :data => repo.parent_id,
     :created_at => repo.created_at
   })
  end
end
 
def create_comment_events_for(repo, project)
  repo.comments.each do |comment|
    puts "creating Comment event on #{project.slug}/#{repo.name}"
    project.events.create({
      :action => Action::COMMENT,
      :target => comment,
      :user => comment.user,
      :created_at => comment.created_at
    })
  end
end
 
def create_merge_request_events_for(repo, project)
  repo.merge_requests.each do |mr|
    puts "creating MergeRequest event on #{project.slug}/#{repo.name}"
    project.events.create({
      :action => Action::REQUEST_MERGE,
      :target => mr,
      :user => mr.user,
      :created_at => mr.created_at,
    })
    unless mr.open?
      puts "creating MergeRequest resolvement event on #{project.slug}/#{repo.name}"
      project.events.create({
        :action => Action::RESOLVE_MERGE_REQUEST,
        :target => mr,
        :user => mr.user,
        :data => mr.status_string,
        :created_at => mr.created_at,
      })
    end
  end
end
 
def create_events_for_repository(repo, project)
  tag_map = repo.git.tags.inject({}){|hsh, t| hsh[t.commit.id] = t.name;hsh}
 
  parsed_commits = {} # Neccesary because of merge
  repo.git.heads.each do |head|
    users_commits = {}
  
    Grit::Commit.find_all(repo.git, head.name, {:since => "1 year ago"}).each do |commit|
      users_commits[commit.committer.email] ||= []
      users_commits[commit.committer.email] << commit
    end
    
    users = User.find(:all, :conditions => ['email in (?)', users_commits.keys] )
    users.each do |user|
      commits = users_commits[user.email]
      puts "\nindexing #{commits.size} commits for #{user.email} in #{project.slug}/#{repo.name}:#{head.name}"
      commits.each_index do |i|
        commit = commits[i]
        previous_commit = commits[i-1]
      
        newrev = commit.id
        next if parsed_commits.has_key?(newrev)
        parsed_commits[newrev] = true
      
        oldrev = previous_commit.id if previous_commit
        current_rev = newrev
        newtype = oldtype = current_rev_type = "commit"
      
        type = repo.git.git.name_rev({}, newrev).last.split("/").first
        if type != "tags"
          type = "heads"
        end
      
        action = :create
        if !oldrev
          action = :create
        else
          if commit.id =~ /^0+$/
            action = :delete
          else
            action = :update
          end
        end
 
        if action != :delete
          newtype = repo.git.git.cat_file({:t => true}, newrev)
        end
 
        if action == :update
          oldtype = repo.git.git.cat_file({:t => true}, oldrev)
        end
 
        if action == :delete
            current_rev = oldrev
            current_rev_type = oldtype
        end
      
 
      
        action_id = nil
        ref = nil
      
        if current_rev_type == "commit"
          if type == "heads"
            case action
              when :create
                action_id = Action::CREATE_BRANCH
                ref = head.name
              when :update
                action_id = Action::COMMIT
                ref = current_rev
              when :delete
                action_id = Action::DELETE_BRANCH
                ref = head.name
            end
          elsif type == "tags"
            if action == :create
              action_id = Action::CREATE_TAG
              ref = tag_map[commit.id]
            elsif action == :delete
              action_id = Action::DELETE_TAG
              ref = tag_map[commit.id]
            end
          end
        elsif current_rev_type == "tag"
          if type == "tags"
            if action == :create
              action_id = Action::CREATE_TAG
              ref = tag_map[commit.id]
            elsif action == :delete
              action_id = Action::DELETE_TAG
              ref = tag_map[commit.id]
            end
          end
        end
      
        print "." if (i % 10 == 1)
        #puts "#{current_rev_type}#{action.inspect} in #{project.slug}/#{repo.name}:#{head.name}: #{commit.short_message}"
        project.events.create({
          :action => action_id || Action::COMMIT,
          :target => repo,
          :user => user,
          :body => commit.message,
          :data => commit.id,
          :created_at => commit.committed_date})
      end
      commits = nil
      puts
    end
    users_commits = nil
  end
  parsed_commits = nil
end
 
def rebuild_project!(project)
  puts "Destroying existing events on #{project.slug}"
  project.events.destroy_all
 
  project.repositories.each do |repo|
    create_events_for_repository(repo, project)
    create_comment_events_for(repo, project)
    create_merge_request_events_for(repo, project)
  end
  create_repo_creation_events_for(project)
end
 
case ARGV[0]
when "all"
  Project.find(:all).each do |project|
    puts
    puts "rebuilding #{project.slug}"
    puts
    begin
      rebuild_project!(project)
      GC.start
    rescue
      puts "!!! failed to rebuild #{project.slug} !!!"
      puts "#{e.class}:#{e.message} \n#{e.backtrace.join("\n ")}"
      puts
      next
    end
  end
else
  project = Project.find(ARGV[0])
  rebuild_project!(project) if project
end