ghtorrent 0.3.1 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,31 +1,3 @@
1
- # Copyright 2012 Georgios Gousios <gousiosg@gmail.com>
2
- #
3
- # Redistribution and use in source and binary forms, with or
4
- # without modification, are permitted provided that the following
5
- # conditions are met:
6
- #
7
- # 1. Redistributions of source code must retain the above
8
- # copyright notice, this list of conditions and the following
9
- # disclaimer.
10
- #
11
- # 2. Redistributions in binary form must reproduce the above
12
- # copyright notice, this list of conditions and the following
13
- # disclaimer in the documentation and/or other materials
14
- # provided with the distribution.
15
- #
16
- # THIS SOFTWARE IS PROVIDED BY BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
- # AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18
- # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
- # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
20
- # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
- # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
- # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
- # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
- # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
- # POSSIBILITY OF SUCH DAMAGE.
28
-
29
1
  require 'net/http'
30
2
  require 'set'
31
3
  require 'open-uri'
@@ -132,6 +104,7 @@ module GHTorrent
132
104
  STDERR.puts "#{url}: #{e.io.status[1]}"
133
105
  return nil
134
106
  else # Server error or HTTP conditions that Github does not report
107
+ STDERR.puts "#{url}"
135
108
  raise e
136
109
  end
137
110
  end
@@ -1,31 +1,3 @@
1
- # Copyright 2012 Georgios Gousios <gousiosg@gmail.com>
2
- #
3
- # Redistribution and use in source and binary forms, with or
4
- # without modification, are permitted provided that the following
5
- # conditions are met:
6
- #
7
- # 1. Redistributions of source code must retain the above
8
- # copyright notice, this list of conditions and the following
9
- # disclaimer.
10
- #
11
- # 2. Redistributions in binary form must reproduce the above
12
- # copyright notice, this list of conditions and the following
13
- # disclaimer in the documentation and/or other materials
14
- # provided with the distribution.
15
- #
16
- # THIS SOFTWARE IS PROVIDED BY BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
- # AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18
- # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
- # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
20
- # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
- # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
- # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
- # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
- # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
- # POSSIBILITY OF SUCH DAMAGE.
28
-
29
1
  module GHTorrent
30
2
  class CallStack
31
3
 
@@ -1,31 +1,3 @@
1
- # Copyright 2012 Georgios Gousios <gousiosg@gmail.com>
2
- #
3
- # Redistribution and use in source and binary forms, with or
4
- # without modification, are permitted provided that the following
5
- # conditions are met:
6
- #
7
- # 1. Redistributions of source code must retain the above
8
- # copyright notice, this list of conditions and the following
9
- # disclaimer.
10
- #
11
- # 2. Redistributions in binary form must reproduce the above
12
- # copyright notice, this list of conditions and the following
13
- # disclaimer in the documentation and/or other materials
14
- # provided with the distribution.
15
- #
16
- # THIS SOFTWARE IS PROVIDED BY BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
- # AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18
- # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
- # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
20
- # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
- # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
- # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
- # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
- # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
- # POSSIBILITY OF SUCH DAMAGE.
28
-
29
1
  require 'rubygems'
30
2
  require 'trollop'
31
3
  require 'daemons'
@@ -1,31 +1,3 @@
1
- # Copyright 2012 Georgios Gousios <gousiosg@gmail.com>
2
- #
3
- # Redistribution and use in source and binary forms, with or
4
- # without modification, are permitted provided that the following
5
- # conditions are met:
6
- #
7
- # 1. Redistributions of source code must retain the above
8
- # copyright notice, this list of conditions and the following
9
- # disclaimer.
10
- #
11
- # 2. Redistributions in binary form must reproduce the above
12
- # copyright notice, this list of conditions and the following
13
- # disclaimer in the documentation and/or other materials
14
- # provided with the distribution.
15
- #
16
- # THIS SOFTWARE IS PROVIDED BY BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
- # AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18
- # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
- # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
20
- # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
- # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
- # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
- # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
- # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
- # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
- # POSSIBILITY OF SUCH DAMAGE.
28
-
29
1
  require 'sequel'
30
2
 
31
3
  module GHTorrent
@@ -65,12 +37,7 @@ module GHTorrent
65
37
  ##
66
38
  # Ensure that a user exists, or fetch its latest state from Github
67
39
  # ==Parameters:
68
- # user::
69
- # The email or login name to lookup the user by
70
- #
71
- # == Returns:
72
- # If the user can be retrieved, it is returned as a Hash. Otherwise,
73
- # the result is nil
40
+ # [user] The email or login name to lookup the user by
74
41
  def get_commit(user, repo, sha)
75
42
 
76
43
  unless sha.match(/[a-f0-9]{40}$/)
@@ -84,14 +51,71 @@ module GHTorrent
84
51
  end
85
52
  end
86
53
 
54
+ ##
55
+ # Add a user as member to a project
56
+ # ==Parameters:
57
+ # [owner] The login of the repository owner
58
+ # [repo] The name of the repository
59
+ # [new_member] The login of the member to add
60
+ # [date_added] The timestamp that the add event took place
61
+ def get_project_member(owner, repo, new_member, date_added)
62
+ transaction do
63
+ ensure_repo(owner, repo)
64
+ ensure_project_member(owner, repo, new_member, date_added)
65
+ end
66
+ end
67
+
68
+ ##
69
+ # Add a commit comment to a commit
70
+ # ==Parameters:
71
+ # [user] The login of the repository owner
72
+ # [repo] The name of the repository
73
+ # [comment_id] The login of the member to add
74
+ # [date_added] The timestamp that the add event took place
75
+ def get_commit_comment(user, repo, comment_id, date_added)
76
+ transaction do
77
+ ensure_repo(user, repo)
78
+ ensure_commit_comment(user, repo, comment_id, date_added)
79
+ end
80
+ end
81
+
82
+ ##
83
+ # Add a watcher to a repository
84
+ # ==Parameters:
85
+ # [owner] The login of the repository owner
86
+ # [repo] The name of the repository
87
+ # [watcher] The login of the member to add
88
+ # [date_added] The timestamp that the add event took place
89
+ def get_watcher(owner, repo, watcher, date_added)
90
+ transaction do
91
+ ensure_repo(owner, repo)
92
+ ensure_watcher(owner, repo, watcher, date_added)
93
+ end
94
+ end
95
+
96
+ ##
97
+ # Add a follower to user
98
+ # ==Parameters:
99
+ # [follower] The login of the repository owner
100
+ # [followed] The name of the repository
101
+ # [date_added] The timestamp that the add event took place
102
+ def get_follower(follower, followed, date_added)
103
+ transaction do
104
+ ensure_user(follower, false, false)
105
+ ensure_user(followed, false, false)
106
+ ensure_user_followers(followed, date_added)
107
+ end
108
+ end
109
+
87
110
  ##
88
111
  # Make sure a commit exists
89
- def ensure_commit(repo, sha, user)
112
+ #
113
+ def ensure_commit(repo, sha, user, comments = true)
90
114
  c = retrieve_commit(repo, sha, user)
91
- store_commit(c, repo, user)
92
- ensure_commit_comments(user, repo, sha)
115
+ stored = store_commit(c, repo, user)
93
116
  ensure_parents(c)
94
- c
117
+ ensure_commit_comments(user, repo, sha) if comments
118
+ stored
95
119
  end
96
120
 
97
121
  ##
@@ -235,6 +259,7 @@ module GHTorrent
235
259
  return u
236
260
  end
237
261
 
262
+
238
263
  ##
239
264
  # Ensure that a user exists, or fetch its latest state from Github
240
265
  # ==Parameters:
@@ -258,19 +283,49 @@ module GHTorrent
258
283
  end
259
284
  end
260
285
 
261
- users.insert(:login => u['login'],
262
- :name => u['name'],
263
- :company => u['company'],
264
- :email => email,
265
- :hireable => boolean(u['hirable']),
266
- :bio => u['bio'],
267
- :location => u['location'],
268
- :type => user_type(u['type']),
269
- :created_at => date(u['created_at']),
270
- :ext_ref_id => u[@ext_uniq])
271
-
272
- info "GHTorrent: New user #{user}"
286
+ if not email.nil?
287
+ # Check whether a user has been added by email before
288
+ byemail = users.first(:email => email)
289
+ unless byemail.nil?
290
+ users.filter(:email => email).update(:login => u['login'],
291
+ :name => u['name'],
292
+ :company => u['company'],
293
+ :hireable => boolean(u['hirable']),
294
+ :bio => u['bio'],
295
+ :location => u['location'],
296
+ :type => user_type(u['type']),
297
+ :created_at => date(u['created_at']),
298
+ :ext_ref_id => u[@ext_uniq]
299
+ )
300
+ info "GHTorrent: Updating user #{user} (email #{email})"
301
+ else
302
+ users.insert(:login => u['login'],
303
+ :name => u['name'],
304
+ :company => u['company'],
305
+ :email => email,
306
+ :hireable => boolean(u['hirable']),
307
+ :bio => u['bio'],
308
+ :location => u['location'],
309
+ :type => user_type(u['type']),
310
+ :created_at => date(u['created_at']),
311
+ :ext_ref_id => u[@ext_uniq])
312
+
313
+ info "GHTorrent: New user #{user}"
314
+ end
315
+ else
316
+ users.insert(:login => u['login'],
317
+ :name => u['name'],
318
+ :company => u['company'],
319
+ :email => email,
320
+ :hireable => boolean(u['hirable']),
321
+ :bio => u['bio'],
322
+ :location => u['location'],
323
+ :type => user_type(u['type']),
324
+ :created_at => date(u['created_at']),
325
+ :ext_ref_id => u[@ext_uniq])
273
326
 
327
+ info "GHTorrent: New user #{user}"
328
+ end
274
329
  users.first(:login => user)
275
330
  else
276
331
  debug "GHTorrent: User #{user} exists"
@@ -285,34 +340,42 @@ module GHTorrent
285
340
  #
286
341
  # ==Parameters:
287
342
  # [user] The user login to find followers by
288
- def ensure_user_followers(user, ts = Time.now)
343
+ def ensure_user_followers(user, date_added = nil)
344
+ followers = @db[:followers]
345
+ userid = @db[:users].first(:login => user)[:id]
289
346
 
290
- followers = retrieve_user_followers(user)
291
- followers.each { |f|
347
+ retrieved = retrieve_user_followers(user)
348
+ retrieved.each { |f|
292
349
  follower = f['login']
293
350
  ensure_user(user, false, false)
294
351
  ensure_user(follower, false, false)
295
352
 
296
- userid = @db[:users].select(:id).first(:login => user)[:id]
297
- followerid = @db[:users].select(:id).first(:login => follower)[:id]
298
- followers = @db[:followers]
353
+ followerid = @db[:users].first(:login => follower)[:id]
354
+
299
355
 
300
356
  if followers.first(:user_id => userid, :follower_id => followerid).nil?
301
- @db[:followers].insert(:user_id => userid,
302
- :follower_id => followerid,
303
- :created_at => ts,
304
- :ext_ref_id => f[@ext_uniq]
357
+ added = if date_added.nil? then Time.now else date_added end
358
+ followers.insert(:user_id => userid,
359
+ :follower_id => followerid,
360
+ :created_at => added,
361
+ :ext_ref_id => f[@ext_uniq]
305
362
  )
306
363
  info "GHTorrent: User #{follower} follows #{user}"
307
364
  else
308
- info "User #{follower} already follows #{user}"
365
+ unless date_added.nil?
366
+ followers.filter(:user_id => userid,
367
+ :follower_id => followerid).\
368
+ update(:created_at => date(date_added))
369
+ info "GHTorrent: Updated follower #{follower} -> #{user}"
370
+ end
371
+ debug "GHTorrent: User #{follower} already follows #{user}"
309
372
  end
310
373
  }
311
374
  end
312
375
 
313
376
  ##
314
377
  # Try to retrieve a user by email. Search the DB first, fall back to
315
- # Github API v2 if unsuccessful.
378
+ # Github search API if unsuccessful.
316
379
  #
317
380
  # ==Parameters:
318
381
  # [email] The email to lookup the user by
@@ -330,7 +393,7 @@ module GHTorrent
330
393
  u = retrieve_user_byemail(email, name)
331
394
 
332
395
  if u.nil? or u['user'].nil? or u['user']['login'].nil?
333
- debug "GHTorrent: Cannot find #{email} through API v2 query"
396
+ debug "GHTorrent: Cannot find #{email} through search API query"
334
397
  users.insert(:email => email,
335
398
  :name => name,
336
399
  :login => (0...8).map { 65.+(rand(25)).chr }.join,
@@ -348,7 +411,7 @@ module GHTorrent
348
411
  :location => u['user']['location'],
349
412
  :created_at => date(u['user']['created_at']),
350
413
  :ext_ref_id => u[@ext_uniq])
351
- debug "GHTorrent: Found #{email} through API v2 query"
414
+ debug "GHTorrent: Found #{email} through search API query"
352
415
  users.first(:email => email)
353
416
  end
354
417
  else
@@ -371,7 +434,8 @@ module GHTorrent
371
434
 
372
435
  ensure_user(user, true, true)
373
436
  repos = @db[:projects]
374
- currepo = repos.first(:name => repo)
437
+ curuser = @db[:users].first(:login => user)
438
+ currepo = repos.first(:owner_id => curuser[:id], :name => repo)
375
439
 
376
440
  if currepo.nil?
377
441
  r = retrieve_repo(user, repo)
@@ -385,13 +449,63 @@ module GHTorrent
385
449
 
386
450
  info "GHTorrent: New repo #{repo}"
387
451
  ensure_commits(user, repo)
388
- repos.first(:name => repo)
452
+ ensure_project_members(user, repo)
453
+ ensure_watchers(user, repo)
454
+ repos.first(:owner_id => curuser[:id], :name => repo)
389
455
  else
390
456
  debug "GHTorrent: Repo #{repo} exists"
391
457
  currepo
392
458
  end
393
459
  end
394
460
 
461
+ ##
462
+ # Make sure that a project has all the registered members defined
463
+ def ensure_project_members(user, repo)
464
+ curuser = @db[:users].first(:login => user)
465
+ currepo = @db[:projects].first(:owner_id => curuser[:id], :name => repo)
466
+ project_members = @db[:project_members].filter(:user_id => curuser[:id],
467
+ :repo_id => currepo[:id])
468
+
469
+ retrieve_repo_collaborators(user, repo).reduce([]) do |acc, x|
470
+ if project_members.find { |y| y[:login] == x['login'] }.nil?
471
+ acc << x
472
+ else
473
+ acc
474
+ end
475
+ end.map { |x| ensure_project_member(user, repo, x['login'], nil) }
476
+ end
477
+
478
+ ##
479
+ # Make sure that a project member exists in a project
480
+ def ensure_project_member(owner, repo, new_member, date_added)
481
+ pr_members = @db[:project_members]
482
+ new_user = ensure_user(new_member, false, false)
483
+ owner_id = @db[:users].first(:login => owner)[:id]
484
+ project = @db[:projects].first(:owner_id => owner_id, :name => repo)
485
+
486
+ memb_exist = pr_members.first(:user_id => new_user[:id],
487
+ :repo_id => project[:id])
488
+
489
+ if memb_exist.nil?
490
+ added = if date_added.nil? then Time.now else date_added end
491
+ retrieved = retrieve_repo_collaborator(owner, repo, new_member)
492
+ pr_members.insert(
493
+ :user_id => new_user[:id],
494
+ :repo_id => project[:id],
495
+ :created_at => date(added),
496
+ :ext_ref_id => retrieved[@ext_uniq]
497
+ )
498
+ info "GHTorrent: Added project member #{repo} -> #{new_member}"
499
+ else
500
+ unless date_added.nil?
501
+ pr_members.filter(:user_id => new_user[:id],
502
+ :repo_id => project[:id])\
503
+ .update(:created_at => date(date_added))
504
+ info "GHTorrent: Updating #{repo} -> #{new_member}"
505
+ end
506
+ end
507
+ end
508
+
395
509
  ##
396
510
  # Make sure that the organizations the user participates into exist
397
511
  #
@@ -404,7 +518,7 @@ module GHTorrent
404
518
  end
405
519
 
406
520
  ##
407
- # Make sure that a user belongs to the provided organization
521
+ # Make sure that a user participates to the provided organization
408
522
  #
409
523
  # ==Parameters:
410
524
  # [user] The login name of the user to check the organizations for
@@ -434,7 +548,7 @@ module GHTorrent
434
548
  # Make sure that an organization exists
435
549
  #
436
550
  # ==Parameters:
437
- # [org] The login name of the organization
551
+ # [organization] The login name of the organization
438
552
  #
439
553
  def ensure_org(organization)
440
554
  org = @db[:users].find(:login => organization, :type => 'org')
@@ -447,39 +561,28 @@ module GHTorrent
447
561
  end
448
562
  end
449
563
 
450
-
451
564
  ##
452
565
  # Get all comments for a commit
453
566
  #
454
567
  # ==Parameters:
455
568
  # [user] The login name of the organization
569
+ # [user] The repository containing the commit whose comments will be retrieved
570
+ # [sha] The commit sha to retrieve comments for
456
571
  def ensure_commit_comments(user, repo, sha)
457
- commit_id = @db[:commits].first(:sha => sha)
458
- stored_comments = @db[:commit_comments].find(:commit_id => commit_id)
459
- commit_commets = retrieve_commit_comments(user, repo, sha)
460
- user_id = @db[:users].first(:login => user)[:id]
572
+ commit_id = @db[:commits].first(:sha => sha)[:id]
573
+ stored_comments = @db[:commit_comments].filter(:commit_id => commit_id)
574
+ commit_comments = retrieve_commit_comments(user, repo, sha)
575
+ #user_id = @db[:users].first(:login => user)[:id]
461
576
 
462
- not_saved = commit_commets.reduce([]) do |acc, x|
463
- if stored_comments.find{|y| y[:comment_id] == x['comment_id']}.nil?
577
+ not_saved = commit_comments.reduce([]) do |acc, x|
578
+ if stored_comments.find{|y| y[:comment_id] == x['id']}.nil?
464
579
  acc << x
465
580
  else
466
581
  acc
467
582
  end
468
583
  end
469
584
 
470
- not_saved.each do |c|
471
- @db[:commit_comments].insert(
472
- :commit_id => commit_id,
473
- :user_id => user_id,
474
- :body => c['body'],
475
- :line => c['line'],
476
- :position => c['position'],
477
- :comment_id => c['id'],
478
- :ext_ref_id => c['ext_ref_id'],
479
- :created_at => date(c['created_at'])
480
- )
481
- info "GHTorrent: Added commit comment #{sha} -> #{user}"
482
- end
585
+ not_saved.map{|x| ensure_commit_comment(user, repo, x['id'], nil)}
483
586
  end
484
587
 
485
588
  ##
@@ -487,12 +590,21 @@ module GHTorrent
487
590
  #
488
591
  # ==Parameters:
489
592
  # [user] The login name of the organization
490
- def ensure_commit_comment(user, repo, id)
593
+ # [repo] The repository containing the commit whose comment will be retrieved
594
+ # [id] The comment id to retrieve
595
+ # [created_at] The timestamp that the comment was made.
596
+ def ensure_commit_comment(user, repo, id, created_at)
491
597
  stored_comment = @db[:commit_comments].first(:comment_id => id)
492
598
 
493
599
  if stored_comment.nil?
494
600
  retrieved = retrieve_commit_comment(user, repo, id)
495
- commit = ensure_commit(repo, retrieved['commit_id'], user)
601
+
602
+ if retrieved.nil?
603
+ debug "GHTorrent: Commit comment #{id} deleted"
604
+ return
605
+ end
606
+
607
+ commit = ensure_commit(repo, retrieved['commit_id'], user, comments = false)
496
608
  user = ensure_user(user, false, false)
497
609
  @db[:commit_comments].insert(
498
610
  :commit_id => commit[:id],
@@ -501,17 +613,66 @@ module GHTorrent
501
613
  :line => retrieved['line'],
502
614
  :position => retrieved['position'],
503
615
  :comment_id => retrieved['id'],
504
- :ext_ref_id => retrieved['ext_ref_id'],
616
+ :ext_ref_id => retrieved[@ext_uniq],
505
617
  :created_at => date(retrieved['created_at'])
506
618
  )
619
+ info "GHTorrent: Added commit comment #{commit[:sha]} -> #{user[:login]}"
507
620
  @db[:commit_comments].first(:comment_id => id)
508
- info "GHTorrent: Added commit comment #{commit[:sha]} -> #{user}"
509
621
  else
510
622
  info "GHTorrent: Commit comment #{id} exists"
511
623
  stored_comment
512
624
  end
513
625
  end
514
626
 
627
+ ##
628
+ # Make sure that
629
+ def ensure_watchers(owner, repo)
630
+ curuser = @db[:users].first(:login => owner)
631
+ currepo = @db[:projects].first(:owner_id => curuser[:id],
632
+ :name => repo)
633
+ watchers = @db[:watchers].filter(:user_id => curuser[:id],
634
+ :repo_id => currepo[:id])
635
+
636
+ retrieve_watchers(owner, repo).reduce([]) do |acc, x|
637
+ if watchers.find { |y| y[:login] == x['login'] }.nil?
638
+ acc << x
639
+ else
640
+ acc
641
+ end
642
+ end.map { |x| ensure_watcher(owner, repo, x['login']) }
643
+ end
644
+
645
+ ##
646
+ # Make sure that a project member exists in a project
647
+ def ensure_watcher(owner, repo, watcher, date_added = nil)
648
+ watchers = @db[:watchers]
649
+ new_watcher = ensure_user(watcher, false, false)
650
+ owner_id = @db[:users].first(:login => owner)[:id]
651
+ project = @db[:projects].first(:owner_id => owner_id, :name => repo)
652
+
653
+ memb_exist = watchers.first(:user_id => new_watcher[:id],
654
+ :repo_id => project[:id])
655
+
656
+ if memb_exist.nil?
657
+ added = if date_added.nil? then Time.now else date_added end
658
+ retrieved = retrieve_watcher(owner, repo, watcher)
659
+ watchers.insert(
660
+ :user_id => new_watcher[:id],
661
+ :repo_id => project[:id],
662
+ :created_at => date(added),
663
+ :ext_ref_id => retrieved[@ext_uniq]
664
+ )
665
+ info "GHTorrent: Added watcher #{repo} -> #{watcher}"
666
+ else
667
+ unless date_added.nil?
668
+ watchers.filter(:user_id => new_watcher[:id],
669
+ :repo_id => project[:id])\
670
+ .update(:created_at => date(date_added))
671
+ info "GHTorrent: Updating #{repo} -> #{watcher}"
672
+ end
673
+ end
674
+ end
675
+
515
676
  private
516
677
 
517
678
  # Store a commit contained in a hash. First check whether the commit exists.
@@ -523,7 +684,6 @@ module GHTorrent
523
684
  author = commit_user(c['author'], c['commit']['author'])
524
685
  commiter = commit_user(c['committer'], c['commit']['committer'])
525
686
 
526
-
527
687
  userid = @db[:users].filter(:login => user).first[:id]
528
688
  repoid = @db[:projects].filter(:owner_id => userid,
529
689
  :name => repo).first[:id]
@@ -535,9 +695,11 @@ module GHTorrent
535
695
  :created_at => date(c['commit']['author']['date']),
536
696
  :ext_ref_id => c[@ext_uniq]
537
697
  )
698
+ commits.first(:sha => c['sha'])
538
699
  debug "GHTorrent: New commit #{repo} -> #{c['sha']} "
539
700
  else
540
701
  debug "GHTorrent: Commit #{repo} -> #{c['sha']} exists"
702
+ commit
541
703
  end
542
704
  end
543
705
 
@@ -569,7 +731,11 @@ module GHTorrent
569
731
  # - yyyy-mm-ddThh:mm:ssZ
570
732
  # - yyyy/mm/dd hh:mm:ss {+/-}hhmm
571
733
  def date(arg)
572
- Time.parse(arg)#.to_i
734
+ if arg.class != Time
735
+ Time.parse(arg)#.to_i
736
+ else
737
+ arg
738
+ end
573
739
  end
574
740
 
575
741
  def is_valid_email(email)