summaryrefslogtreecommitdiffstats
path: root/script/rebuild_events
blob: d34cf9e24081fcc49425bdf24de96ab055b67985 (plain)
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
#!/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