aweplug 1.0.0.a2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/.rspec +3 -0
- data/Gemfile +3 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.adoc +3 -0
- data/README.md +29 -0
- data/Rakefile +51 -0
- data/aweplug.gemspec +29 -0
- data/lib/aweplug/extensions/identities.rb +187 -0
- data/lib/aweplug/extensions/identity/confluence.rb +107 -0
- data/lib/aweplug/extensions/identity/github.rb +230 -0
- data/lib/aweplug/extensions/identity/gravatar.rb +117 -0
- data/lib/aweplug/extensions/identity/jbosscommunity.rb +35 -0
- data/lib/aweplug/extensions/kramdown_quickstart.rb +41 -0
- data/lib/aweplug/extensions/sections.rb +30 -0
- data/lib/aweplug/helpers/.gitkeep +0 -0
- data/lib/aweplug/helpers/git_commit_metadata.rb +23 -0
- data/lib/aweplug/helpers/kramdown_metadata.rb +58 -0
- data/lib/aweplug/transformers/.gitkeep +0 -0
- data/lib/aweplug/version.rb +4 -0
- data/lib/aweplug.rb +5 -0
- data/spec/aweplug/extensions/identity/collector_spec.rb +24 -0
- data/spec/aweplug/extensions/identity/github_spec.rb +7 -0
- data/spec/aweplug/extensions/identity/storage_spec.rb +24 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/support/aweplug/extensions/identity/crawler_examples.rb +13 -0
- metadata +160 -0
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
coverage
|
6
|
+
InstalledFiles
|
7
|
+
lib/bundler/man
|
8
|
+
pkg
|
9
|
+
rdoc
|
10
|
+
spec/reports
|
11
|
+
test/tmp
|
12
|
+
test/version_tmp
|
13
|
+
tmp
|
14
|
+
Gemfile.lock
|
15
|
+
|
16
|
+
# YARD artifacts
|
17
|
+
.yardoc
|
18
|
+
_yardoc
|
19
|
+
doc/
|
20
|
+
.bundle
|
21
|
+
vendor/bundle
|
22
|
+
vendor/cache
|
23
|
+
pkg
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 LightGuard
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.adoc
ADDED
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Aweplug
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'aweplug'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install aweplug
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'aweplug/version'
|
4
|
+
require 'guard'
|
5
|
+
|
6
|
+
GEMFILE = "aweplug-#{Aweplug::VERSION}.gem"
|
7
|
+
|
8
|
+
task :default => :build
|
9
|
+
|
10
|
+
desc "Run all tests and build the gem"
|
11
|
+
task :build => 'test:spec' do
|
12
|
+
system "gem build aweplug.gemspec"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Build and install the gem locally"
|
16
|
+
task :install => :build do
|
17
|
+
system "gem install -l -f #{GEMFILE}"
|
18
|
+
end
|
19
|
+
|
20
|
+
namespace :release do
|
21
|
+
desc "Release the gem to rubygems"
|
22
|
+
task :push => [ :build, :tag ] do
|
23
|
+
system "gem push #{GEMFILE}"
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Create tag #{Aweplug::VERSION} in git"
|
27
|
+
task :tag do
|
28
|
+
system "git tag #{Aweplug::VERSION}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
namespace :test do
|
33
|
+
if !defined?(RSpec)
|
34
|
+
puts "spec targets require RSpec"
|
35
|
+
else
|
36
|
+
desc "Run all specifications"
|
37
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
38
|
+
t.pattern = 'spec/**/*_spec.rb'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "Start Guard to listen for changes and run specs"
|
43
|
+
task :guard do
|
44
|
+
Guard.start(:guardfile => 'Guardfile')
|
45
|
+
Guard.run_all
|
46
|
+
while ::Guard.running do
|
47
|
+
sleep 0.5
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
data/aweplug.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'aweplug/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "aweplug"
|
8
|
+
gem.version = Aweplug::VERSION
|
9
|
+
gem.authors = ["LightGuard"]
|
10
|
+
gem.email = ["lightguard.jp@gmail.com"]
|
11
|
+
gem.description = %q{A set of Awestruct extensions for building a project website}
|
12
|
+
gem.summary = %q{This set of Awestruct extensions includes helpful tools,
|
13
|
+
extensions and helpers for building a website using Awestruct.
|
14
|
+
It includes extensions for accessing Github, JIRA, managing identities and others.}
|
15
|
+
gem.homepage = "https://github.com/awestruct/aweplug"
|
16
|
+
|
17
|
+
gem.files = `git ls-files`.split($/)
|
18
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
|
+
gem.require_paths = ["lib"]
|
21
|
+
|
22
|
+
#gem.add_dependency 'awestruct', '>= 0.5.1'
|
23
|
+
gem.add_dependency 'octokit', '>= 1.24.0'
|
24
|
+
gem.add_dependency 'faraday', '>= 0.8.7'
|
25
|
+
gem.add_dependency 'faraday_middleware', '>= 0.9.0'
|
26
|
+
|
27
|
+
gem.add_development_dependency 'guard-rspec', '~> 3.0.0'
|
28
|
+
gem.add_development_dependency 'rake', '~> 10.0.4'
|
29
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'aweplug/extensions/restclient_extensions'
|
3
|
+
require 'aweplug/extensions/identity/github'
|
4
|
+
require 'aweplug/extensions/identity/gravatar'
|
5
|
+
require 'aweplug/extensions/identity/confluence'
|
6
|
+
require 'aweplug/extensions/identity/jbosscommunity'
|
7
|
+
|
8
|
+
module Aweplug
|
9
|
+
module Extensions
|
10
|
+
module Identities
|
11
|
+
# QUESTION should we call this Initializer or Loader instead?
|
12
|
+
class Storage
|
13
|
+
def initialize(opts = {})
|
14
|
+
@use_data_cache = opts[:use_data_cache] || true
|
15
|
+
end
|
16
|
+
|
17
|
+
# Internal: Awestruct calls this method during site generation.
|
18
|
+
# Iterates through all the different identity in the site and finds
|
19
|
+
# information about them.
|
20
|
+
#
|
21
|
+
# site - This must be the site object provided by awestruct
|
22
|
+
#
|
23
|
+
# Returns nothing
|
24
|
+
def execute(site)
|
25
|
+
data_file = File.join(site.tmp_dir, 'datacache', 'identity.yml')
|
26
|
+
loaded = false
|
27
|
+
identities = []
|
28
|
+
if @use_data_cache and File.exist? data_file
|
29
|
+
identities = YAML.load_file data_file
|
30
|
+
loaded = true
|
31
|
+
else
|
32
|
+
if site.identities
|
33
|
+
identities = site.identities.map { |i| OpenStruct.new i }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
identities.extend(Locators)
|
37
|
+
identities.loaded = loaded
|
38
|
+
site.identities = identities
|
39
|
+
end
|
40
|
+
|
41
|
+
module Locators
|
42
|
+
attr_accessor :loaded
|
43
|
+
|
44
|
+
def lookup(username, create = false)
|
45
|
+
identity = self.find { |e| username.eql? e.username } ||
|
46
|
+
self.find { |e| username.eql? e.jboss_username }
|
47
|
+
if create and identity.nil?
|
48
|
+
identity = OpenStruct.new({:username => username})
|
49
|
+
if block_given?
|
50
|
+
yield identity
|
51
|
+
end
|
52
|
+
self << identity
|
53
|
+
end
|
54
|
+
identity
|
55
|
+
end
|
56
|
+
|
57
|
+
def lookup_by_name(name, create = false)
|
58
|
+
search = name.downcase
|
59
|
+
identity = self.find { |e| search.eql? e.name.to_s.downcase }
|
60
|
+
if create and identity.nil?
|
61
|
+
identity = OpenStruct.new({:name => name})
|
62
|
+
if block_given?
|
63
|
+
yield identity
|
64
|
+
end
|
65
|
+
self << identity
|
66
|
+
end
|
67
|
+
identity
|
68
|
+
end
|
69
|
+
|
70
|
+
def lookup_by_contributor(contributor)
|
71
|
+
identity = self.find { |e| e.contributor and e.contributor.emails and e.contributor.emails.include? contributor.email }
|
72
|
+
if identity.nil?
|
73
|
+
# Indication that we have a mismatched account
|
74
|
+
puts "Could not find contributor with e-mail " + contributor.email
|
75
|
+
end
|
76
|
+
identity
|
77
|
+
end
|
78
|
+
|
79
|
+
def lookup_by_email(email, create = false)
|
80
|
+
identity = self.find { |e| email.eql? e.email or !e.emails.nil? and e.emails.include? email }
|
81
|
+
if create and identity.nil?
|
82
|
+
identity = OpenStruct.new({:email => email})
|
83
|
+
if block_given?
|
84
|
+
yield identity
|
85
|
+
end
|
86
|
+
self << identity
|
87
|
+
end
|
88
|
+
identity
|
89
|
+
end
|
90
|
+
|
91
|
+
def lookup_by_github_id(github_id, create = false)
|
92
|
+
identity = self.find { |e| github_id.eql? e.github_id }
|
93
|
+
if create and identity.nil?
|
94
|
+
identity = OpenStruct.new({:github_id => github_id})
|
95
|
+
if block_given?
|
96
|
+
yield identity
|
97
|
+
end
|
98
|
+
self << identity
|
99
|
+
end
|
100
|
+
identity
|
101
|
+
end
|
102
|
+
|
103
|
+
def lookup_by_twitter_username(username)
|
104
|
+
self.find { |e| !e.twitter.nil? and username.eql? e.twitter.username }
|
105
|
+
end
|
106
|
+
|
107
|
+
def locate(*query)
|
108
|
+
query.map! { |e| e.downcase }
|
109
|
+
self.find { |e| not ([e.username, e.name.to_s.downcase, e.email] & query).empty? }
|
110
|
+
end
|
111
|
+
|
112
|
+
def core_team()
|
113
|
+
self.select { |e| e.core }
|
114
|
+
end
|
115
|
+
|
116
|
+
def contributors()
|
117
|
+
self.select { |e| e.contributor }
|
118
|
+
end
|
119
|
+
|
120
|
+
def speakers()
|
121
|
+
self.select { |e| e.speaker }
|
122
|
+
end
|
123
|
+
|
124
|
+
def translators()
|
125
|
+
self.select { |e| e.translator }
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
module IdentityHelper
|
131
|
+
# SEMI-HACK this should received contributions from crawlers
|
132
|
+
def url
|
133
|
+
self.jbosscommunity ? self.jbosscommunity.profile_url : self.github.profile_url
|
134
|
+
end
|
135
|
+
|
136
|
+
# TODO support for CSS class, or just attributes in general
|
137
|
+
def to_link
|
138
|
+
"<a href=\"#{self.url}\">#{self.name}</a>"
|
139
|
+
end
|
140
|
+
|
141
|
+
def to_s
|
142
|
+
self.name
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class Collect
|
147
|
+
def initialize(*collectors)
|
148
|
+
@collectors = collectors
|
149
|
+
end
|
150
|
+
|
151
|
+
def execute(site)
|
152
|
+
if !site.identities.loaded
|
153
|
+
@collectors.each do |c|
|
154
|
+
c.collect(site.identities)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class Crawl
|
161
|
+
def initialize(*crawlers)
|
162
|
+
@crawlers = crawlers
|
163
|
+
end
|
164
|
+
|
165
|
+
def execute(site)
|
166
|
+
site.identities.each do |i|
|
167
|
+
@crawlers.each do |c|
|
168
|
+
c.crawl(i) if !site.identities.loaded
|
169
|
+
i.extend(IdentityHelper)
|
170
|
+
c.enhance(i) if c.respond_to? 'enhance'
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class Cache
|
177
|
+
def execute(site)
|
178
|
+
data_file = File.join(site.tmp_dir, 'datacache', 'identity.yml')
|
179
|
+
FileUtils.mkdir_p File.dirname data_file
|
180
|
+
File.open(data_file, 'w') do |out|
|
181
|
+
YAML.dump site.identities, out
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Aweplug
|
4
|
+
module Extensions
|
5
|
+
module Identity
|
6
|
+
module Confluence
|
7
|
+
class Crawler
|
8
|
+
SESSION_PATH = '/rest/prototype/1/session'
|
9
|
+
SEARCH_PATH = '/rest/prototype/1/search/user'
|
10
|
+
SEARCH_PARAM = 'query'
|
11
|
+
|
12
|
+
# Public: Initialize a Crawler
|
13
|
+
#
|
14
|
+
# base_url - The String of the base confluence url, no trailing slash
|
15
|
+
# opts[:assign_to] - The String OpenStruct keys to send the data
|
16
|
+
# opts[:identity_search_keys] - The String OpenStruct keys to use to locate the search query
|
17
|
+
# opts[:assign_username_to] - The String OpenStruct key to which to assign the username
|
18
|
+
# opts[:auth_file] - The File containing the authentication credentials for secure requests
|
19
|
+
def initialize(base_url, opts = {})
|
20
|
+
@base_url = base_url
|
21
|
+
@identity_search_keys = opts[:identity_search_keys] || ['name']
|
22
|
+
@assign_to = opts[:assign_to] || 'confluence'
|
23
|
+
@assign_username_to = opts[:assign_username_to]
|
24
|
+
@auth_file = opts[:auth_file]
|
25
|
+
@session_cookie = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def crawl(identity)
|
29
|
+
search = nil
|
30
|
+
queries = []
|
31
|
+
data = nil
|
32
|
+
@identity_search_keys.each do |k|
|
33
|
+
search = identity.send(k)
|
34
|
+
next if search.nil?
|
35
|
+
# lowercase and remove middle names (shouldn't affect usernames)
|
36
|
+
search = search.downcase.gsub(/^([^ ]+ ?).*?([^ ]+)$/, '\1\2')
|
37
|
+
# don't search on same string twice
|
38
|
+
next if queries.include? search
|
39
|
+
queries << search
|
40
|
+
cleansed_query = search.gsub(' ', '-')
|
41
|
+
url = File.join(@base_url, SEARCH_PATH) + '?query=' + URI.encode(search)
|
42
|
+
data = RestClient.get(url, :cache_key => "confluence/query-#{cleansed_query}.json", :accept => 'application/json')
|
43
|
+
if data['totalSize'].to_i == 0
|
44
|
+
#puts "No results, advancing confluence user crawler to next query string for #{search}"
|
45
|
+
data = nil
|
46
|
+
#elsif data['totalSize'] > 1
|
47
|
+
# puts "Too many results, skipping confluence user crawler for #{search}."
|
48
|
+
# data = nil
|
49
|
+
else
|
50
|
+
break
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
if data.nil?
|
55
|
+
if queries.empty?
|
56
|
+
puts "No property found to search, skipping confluence user crawler for #{identity.name}"
|
57
|
+
else
|
58
|
+
puts "No results, skipping confluence user crawler for #{queries.join ' / '}"
|
59
|
+
end
|
60
|
+
return
|
61
|
+
end
|
62
|
+
|
63
|
+
user = data['result'].first
|
64
|
+
username = user['username']
|
65
|
+
url = user['link'].select{|l| l['href'].end_with? "~#{username}" }.first['href']
|
66
|
+
identity.send(@assign_to + '=', OpenStruct.new({:username => username, :profile_url => url}))
|
67
|
+
if !@assign_username_to.nil?
|
68
|
+
identity.send(@assign_username_to + '=', username)
|
69
|
+
end
|
70
|
+
|
71
|
+
get_session_cookie()
|
72
|
+
if @session_cookie
|
73
|
+
profile = RestClient.get(url, :cache_key => "confluence/user-#{username}.html", :cookie => @session_cookie)
|
74
|
+
if profile.match(/ id="email".*?>(.+?)</)
|
75
|
+
replace = {' dot ' => '.', ' at ' => '@'}
|
76
|
+
email = $1.gsub(/ (dot|at) /) {|m| replace[m]}
|
77
|
+
identity.email = email if identity.email.nil?
|
78
|
+
identity.emails ||= []
|
79
|
+
identity.emails |= [identity.email, email]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_session_cookie()
|
86
|
+
if @session_cookie.nil?
|
87
|
+
@session_cookie = false
|
88
|
+
credentials = nil
|
89
|
+
if !@auth_file.nil?
|
90
|
+
if File.exist? @auth_file
|
91
|
+
credentials = File.read(@auth_file)
|
92
|
+
elsif Pathname.new(@auth_file).relative? and File.exist? File.join(ENV['HOME'], @auth_file)
|
93
|
+
credentials = File.read(File.join(ENV['HOME'], @auth_file))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
if !credentials.nil?
|
97
|
+
url = @base_url.gsub(/^(https?:\/\/)/, '\1' + credentials.chomp + '@') + SESSION_PATH
|
98
|
+
response = RestClient.head(url)
|
99
|
+
@session_cookie = response.headers[:set_cookie].first.split(';').first
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,230 @@
|
|
1
|
+
module Aweplug
|
2
|
+
module Extensions
|
3
|
+
module Identity
|
4
|
+
module GitHub
|
5
|
+
CONTRIBUTORS_URL_TEMPLATE = 'https://api.github.com/repos/%s/%s/contributors'
|
6
|
+
TEAM_MEMBERS_URL_TEMPLATE = 'https://api.github.com/teams/%s/members'
|
7
|
+
USER_URL_TEMPLATE = 'https://api.github.com/users/%s'
|
8
|
+
|
9
|
+
# It appears that all github users have a gravatar_id
|
10
|
+
AVATAR_URL_TEMPLATE = 'http://gravatar.com/avatar/%s?s=%i'
|
11
|
+
# TODO make the default avatar configurable
|
12
|
+
FALLBACK_AVATAR_URL_TEMPLATE = 'https://community.jboss.org/people/sbs-default-avatar/avatar/%i.png'
|
13
|
+
module IdentityHelper
|
14
|
+
def avatar_url(size = 48)
|
15
|
+
if !self.gravatar_id.nil?
|
16
|
+
AVATAR_URL_TEMPLATE % [self.gravatar_id, size]
|
17
|
+
else
|
18
|
+
FALLBACK_URL_TEMPLATE % size
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Collector
|
24
|
+
|
25
|
+
def initialize(opts = {})
|
26
|
+
@repositories = []
|
27
|
+
@match_filters = []
|
28
|
+
@teams = opts[:teams]
|
29
|
+
@auth_file = opts[:auth_file]
|
30
|
+
@credentials = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_repository(repository)
|
34
|
+
@repositories << repository
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_match_filter(match_filter)
|
38
|
+
@match_filters << match_filter
|
39
|
+
#File.open('/tmp/committers.yml', 'w') do |out|
|
40
|
+
# YAML.dump(match_filter, out)
|
41
|
+
#end
|
42
|
+
end
|
43
|
+
|
44
|
+
def collect(identities)
|
45
|
+
visited = []
|
46
|
+
@repositories.each do |r|
|
47
|
+
url = CONTRIBUTORS_URL_TEMPLATE % [r.owner, r.path]
|
48
|
+
contributors = RestClient.get url, :accept => 'application/json'
|
49
|
+
contributors.each do |acct|
|
50
|
+
github_id = acct['login'].downcase
|
51
|
+
author = nil
|
52
|
+
@match_filters.each do |filter|
|
53
|
+
author = filter.values.find { |candidate| candidate.github_id.eql? github_id }
|
54
|
+
break unless author.nil?
|
55
|
+
end
|
56
|
+
if author.nil?
|
57
|
+
#puts "Skipping non-Arquillian contributor #{github_id} in repository #{r.owner}/#{r.path}"
|
58
|
+
next
|
59
|
+
end
|
60
|
+
identity = identities.lookup_by_github_id(github_id, true)
|
61
|
+
github_acct_to_identity(acct, author, identity)
|
62
|
+
visited << github_id
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# github doesn't keep perfect records of contributors, so handle those omitted contributors
|
67
|
+
@match_filters.each do |filter|
|
68
|
+
filter.values.select { |author| !author.github_id.nil? and !visited.include? author.github_id }.each do |author|
|
69
|
+
github_id = author.github_id
|
70
|
+
puts "Manually adding #{author.name} (#{github_id}) as a contributor"
|
71
|
+
url = USER_URL_TEMPLATE % [github_id]
|
72
|
+
user = RestClient.get url, :accept => 'application/json'
|
73
|
+
identity = identities.lookup_by_github_id(github_id, true)
|
74
|
+
github_acct_to_identity(user, author, identity)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
if !@teams.nil?
|
79
|
+
get_credentials()
|
80
|
+
if @credentials
|
81
|
+
@teams.each do |team|
|
82
|
+
url = TEAM_MEMBERS_URL_TEMPLATE % team[:id]
|
83
|
+
url = url.gsub(/^(https?:\/\/)/, '\1' + @credentials.chomp + '@')
|
84
|
+
members = RestClient.get(url, :accept => 'application/json')
|
85
|
+
members.each do |m|
|
86
|
+
github_id = m['login']
|
87
|
+
identity = identities.lookup_by_github_id(github_id)
|
88
|
+
# identity should not be null, mostly for testing
|
89
|
+
if !identity.nil?
|
90
|
+
identity.send(team[:name] + '=', true)
|
91
|
+
identity.teams = [] if identity.teams.nil?
|
92
|
+
identity.teams << team[:name]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def github_acct_to_identity(acct, author, identity)
|
101
|
+
# setup if first visit
|
102
|
+
if identity.github.nil? or identity.github.contributions.nil?
|
103
|
+
identity.github = OpenStruct.new if identity.github.nil?
|
104
|
+
identity.github.contributions = acct.has_key?('contributions') ? acct['contributions'] : 0
|
105
|
+
identity.github_url = acct['url'].downcase
|
106
|
+
identity.gravatar_id = acct['gravatar_id']
|
107
|
+
# author contains the commits we counted from analyzing the repositories
|
108
|
+
identity.contributor = author
|
109
|
+
identity.email = author.emails.first if identity.email.nil?
|
110
|
+
identity.emails ||= []
|
111
|
+
identity.emails |= [identity.email, author.emails.first]
|
112
|
+
# alias for convenience
|
113
|
+
identity.commits = author.commits
|
114
|
+
# assume they want their commit name as the preferred name (unless it's an email)
|
115
|
+
if identity.name.nil? and author.name.index('@').nil?
|
116
|
+
if !author.name.index(' ').nil?
|
117
|
+
# FIXME this could be made into a smarter utility function
|
118
|
+
identity.name = author.name.split(' ').map { |n| n.capitalize }.join(' ')
|
119
|
+
# special exception for Lincoln :)
|
120
|
+
identity.name.gsub!('Iii', 'III')
|
121
|
+
else
|
122
|
+
identity.name = author.name.capitalize
|
123
|
+
end
|
124
|
+
end
|
125
|
+
# if been there, just add contributions according to github
|
126
|
+
else
|
127
|
+
identity.github.contributions += acct.has_key?('contributions') ? acct['contributions'] : 0
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def get_credentials()
|
132
|
+
if @credentials.nil?
|
133
|
+
@credentials = false
|
134
|
+
if !@auth_file.nil?
|
135
|
+
if File.exist? @auth_file
|
136
|
+
@credentials = File.read(@auth_file)
|
137
|
+
elsif Pathname.new(@auth_file).relative? and File.exist? File.join(ENV['HOME'], @auth_file)
|
138
|
+
@credentials = File.read(File.join(ENV['HOME'], @auth_file))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class Crawler
|
146
|
+
|
147
|
+
def initialize(opts = {})
|
148
|
+
@auth_file = opts[:auth_file]
|
149
|
+
@credentials = nil
|
150
|
+
end
|
151
|
+
|
152
|
+
PROFILE_URL_TEMPLATE = 'https://api.github.com/users/%s'
|
153
|
+
|
154
|
+
def enhance(identity)
|
155
|
+
identity.extend(IdentityHelper)
|
156
|
+
end
|
157
|
+
|
158
|
+
def get_credentials()
|
159
|
+
if @credentials.nil?
|
160
|
+
@credentials = false
|
161
|
+
if !@auth_file.nil?
|
162
|
+
if File.exist? @auth_file
|
163
|
+
@credentials = File.read(@auth_file)
|
164
|
+
elsif Pathname.new(@auth_file).relative? and File.exist? File.join(ENV['HOME'], @auth_file)
|
165
|
+
@credentials = File.read(File.join(ENV['HOME'], @auth_file))
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def crawl(identity)
|
172
|
+
url = identity.github_url
|
173
|
+
if url.nil?
|
174
|
+
if !identity.github_id.nil?
|
175
|
+
url = PROFILE_URL_TEMPLATE % identity.github_id
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# can't find user, give up (no github id or explicit url)
|
180
|
+
if url.nil?
|
181
|
+
return
|
182
|
+
end
|
183
|
+
|
184
|
+
get_credentials()
|
185
|
+
url = url.gsub(/^(https?:\/\/)/, '\1' + @credentials.chomp + '@')
|
186
|
+
data = RestClient.get url, :accept => 'application/json'
|
187
|
+
identity.github_id = data['login'].downcase
|
188
|
+
identity.username = identity.github_id
|
189
|
+
identity.github = OpenStruct.new if identity.github.nil?
|
190
|
+
identity.github.merge!(OpenStruct.new({
|
191
|
+
:id => data['id'],
|
192
|
+
:created => data['created_at'],
|
193
|
+
:username => identity.username,
|
194
|
+
:profile_url => data['html_url'].downcase
|
195
|
+
}))
|
196
|
+
# only overwrite name if it's longer than the one already there
|
197
|
+
if !data['name'].nil? and (identity.name.nil? or data['name'].length > identity.name.length)
|
198
|
+
identity.name = data['name'].titleize
|
199
|
+
end
|
200
|
+
identity.emails ||= []
|
201
|
+
identity.emails |= [identity.email].compact
|
202
|
+
keys_to_identity = ['email', 'gravatar_id', 'blog', 'location', 'bio', 'company']
|
203
|
+
# merge keys, overwriting duplicates
|
204
|
+
identity.merge!(OpenStruct.new(data.select { |k, v|
|
205
|
+
!v.to_s.strip.empty? and keys_to_identity.include? k
|
206
|
+
}))
|
207
|
+
if identity.email
|
208
|
+
identity.email = identity.email.downcase
|
209
|
+
end
|
210
|
+
# append email if we got a new one
|
211
|
+
identity.emails |= [identity.email]
|
212
|
+
# fix blog urls missing http:// prefix
|
213
|
+
if !identity.blog.nil? and identity.blog !~ /^https?:\/\//
|
214
|
+
identity.blog = 'http://' + identity.blog
|
215
|
+
end
|
216
|
+
|
217
|
+
# manually credited commits
|
218
|
+
if identity.commits and !identity.contributor
|
219
|
+
identity.contributor = OpenStruct.new({
|
220
|
+
:commits => identity.commits,
|
221
|
+
:emails => [identity.email],
|
222
|
+
:name => identity.name
|
223
|
+
})
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module Aweplug
|
4
|
+
module Extensions
|
5
|
+
module Identity
|
6
|
+
module Gravatar
|
7
|
+
class Crawler
|
8
|
+
API_URL_TEMPLATE = 'http://en.gravatar.com/%s.json'
|
9
|
+
LANYRD_PROFILE_URL_TEMPLATE = 'http://lanyrd.com/profile/%s'
|
10
|
+
|
11
|
+
def enhance(identity)
|
12
|
+
#identity.extend(IdentityHelper)
|
13
|
+
end
|
14
|
+
|
15
|
+
def crawl(identity)
|
16
|
+
hash = identity.gravatar_id
|
17
|
+
if hash.nil?
|
18
|
+
hash = Digest::MD5.new().update(identity.email.downcase).hexdigest
|
19
|
+
end
|
20
|
+
url = API_URL_TEMPLATE % hash
|
21
|
+
response = RestClient.get(url, :user_agent => "rest-client") do |rsp, req, res, &blk|
|
22
|
+
if rsp.code.eql? 404
|
23
|
+
#rsp = RestClient::Response.create('{}', rsp.net_http_res, rsp.args)
|
24
|
+
rsp.instance_variable_set(:@code, 200)
|
25
|
+
rsp
|
26
|
+
else
|
27
|
+
rsp.return!(req, res, &blk)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
data = JSON.parse response
|
32
|
+
|
33
|
+
if data.empty?
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
entry = data['entry'].first
|
38
|
+
|
39
|
+
keys_to_gravatar = {
|
40
|
+
'id' => 'id',
|
41
|
+
'hash' => 'hash',
|
42
|
+
'profileUrl' => 'profile_url'
|
43
|
+
}
|
44
|
+
identity.gravatar = OpenStruct.new(entry.select { |k, v|
|
45
|
+
!v.to_s.strip.empty? and keys_to_gravatar.has_key? k
|
46
|
+
}.inject({}) { |h, (k, v)| h.store(keys_to_gravatar[k], v); h })
|
47
|
+
|
48
|
+
keys_to_identity = {
|
49
|
+
'preferredUsername' => 'preferred_username',
|
50
|
+
'displayName' => 'name_cloak',
|
51
|
+
'aboutMe' => 'bio',
|
52
|
+
'currentLocation' => 'location'
|
53
|
+
}
|
54
|
+
identity.merge!(OpenStruct.new(entry.select { |k, v|
|
55
|
+
!v.to_s.strip.empty? and keys_to_identity.has_key? k
|
56
|
+
}.inject({}) { |h, (k, v)| h.store(keys_to_identity[k], v); h }), false)
|
57
|
+
|
58
|
+
# TODO check if we need a merge here
|
59
|
+
if entry.has_key? 'name' and !entry['name'].to_s.strip.empty?
|
60
|
+
if identity.names.nil?
|
61
|
+
identity.names = OpenStruct.new(entry['name'])
|
62
|
+
end
|
63
|
+
if identity.name.nil?
|
64
|
+
identity.name = identity.names.formatted
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
if entry.has_key? 'email' and !entry['email'].to_s.strip.empty?
|
69
|
+
email = entry['email'].downcase
|
70
|
+
identity.email = email if identity.email.nil?
|
71
|
+
identity.emails ||= []
|
72
|
+
identity.emails |= [identity.email, email]
|
73
|
+
end
|
74
|
+
|
75
|
+
(entry['accounts'] || []).each do |a|
|
76
|
+
astruct = OpenStruct.new(a)
|
77
|
+
if identity.send(a['shortname']).nil?
|
78
|
+
identity.send(a['shortname'] + '=', astruct)
|
79
|
+
else
|
80
|
+
identity.send(a['shortname']).merge!(astruct)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# grab twitter usernames supplied by _config/identity.yml
|
85
|
+
if identity.twitter.nil? and !identity.twitter_username.nil?
|
86
|
+
identity.twitter = OpenStruct.new({
|
87
|
+
:username => identity.twitter_username,
|
88
|
+
:url => 'http://twitter.com/' + identity.twitter_username
|
89
|
+
})
|
90
|
+
end
|
91
|
+
|
92
|
+
# QUESTION do we need the speaker flag check?
|
93
|
+
if identity.speaker and !identity.twitter.nil? and identity.lanyrd.nil?
|
94
|
+
identity.lanyrd = OpenStruct.new({
|
95
|
+
:username => identity.twitter.username,
|
96
|
+
:profile_url => LANYRD_PROFILE_URL_TEMPLATE % identity.twitter.username
|
97
|
+
})
|
98
|
+
end
|
99
|
+
|
100
|
+
# FIXME either map url to profile_url, or change everywhere else
|
101
|
+
(entry['urls'] || []).each do |u|
|
102
|
+
identity.urls = [] if identity.urls.nil?
|
103
|
+
identity.urls << OpenStruct.new(u)
|
104
|
+
if identity.blog.to_s.empty? and u['title'] =~ /blog/i
|
105
|
+
identity.blog = u['value']
|
106
|
+
end
|
107
|
+
if identity.homepage.to_s.empty? and u['title'] =~ /personal/i
|
108
|
+
identity.homepage = u['value']
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Aweplug
|
2
|
+
module Extensions
|
3
|
+
module Identity
|
4
|
+
module JBossCommunity
|
5
|
+
class Crawler
|
6
|
+
PROFILE_URL_TEMPLATE = 'https://community.jboss.org/people/%s'
|
7
|
+
|
8
|
+
def crawl(identity)
|
9
|
+
if !identity.jboss_username.nil?
|
10
|
+
identity.jbosscommunity = OpenStruct.new({
|
11
|
+
:username => identity.jboss_username,
|
12
|
+
:profile_url => PROFILE_URL_TEMPLATE % identity.jboss_username
|
13
|
+
})
|
14
|
+
end
|
15
|
+
|
16
|
+
if identity.jbosscommunity.nil? and !identity.urls.nil?
|
17
|
+
identity.urls.each do |u|
|
18
|
+
if u.title =~ /jboss community/i
|
19
|
+
identity.jbosscommunity = OpenStruct.new({
|
20
|
+
:username => u.value.split('/').last,
|
21
|
+
:profile_url => u.value
|
22
|
+
})
|
23
|
+
identity.jboss_username = identity.jbosscommunity.username
|
24
|
+
break
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
# TODO actually rip data from community.jboss.org
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'kramdown'
|
3
|
+
require 'aweplug/helpers/git_commit_metadata'
|
4
|
+
require 'aweplug/helpers/kramdown_metadata'
|
5
|
+
|
6
|
+
module Aweplug
|
7
|
+
module Extensions
|
8
|
+
module Kramdown
|
9
|
+
class Quickstart
|
10
|
+
include Aweplug::Helper::Git::Commit::Metadata
|
11
|
+
|
12
|
+
def initialize repository, layout
|
13
|
+
@repo = repository
|
14
|
+
@layout = layout
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute site
|
18
|
+
Dir["#{@repo}/**/README.md"].each do |file|
|
19
|
+
page = add_to_site site, file
|
20
|
+
|
21
|
+
metadata = extract_metadata(file)
|
22
|
+
metadata[:commits] = commit_info @repo, Pathname.new(file)
|
23
|
+
|
24
|
+
page.send 'metadata=', @metadata
|
25
|
+
# TODO: Upload to DCP
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def extract_metadata(file)
|
30
|
+
(Kramdown::Document.new File.readlines(file).join, :input => 'QuickStartParser').root.options[:metadata]
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_to_site(site, file)
|
34
|
+
page = site.engine.load_site_page file
|
35
|
+
page.layout = @layout
|
36
|
+
page
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'asciidoctor'
|
2
|
+
|
3
|
+
module Awestruct
|
4
|
+
module Extensions
|
5
|
+
# Public: Parses (AsciiDoc files currently) and pulls out h2 sections
|
6
|
+
# (and their contents), setting them as first class page variables.
|
7
|
+
#
|
8
|
+
# Examples
|
9
|
+
#
|
10
|
+
# extension Awestruct::Extensions::Sections.new
|
11
|
+
class Sections
|
12
|
+
# Internal: Looks for all AsciiDoc files and pulls out the sections,
|
13
|
+
# adding them to the page variable.
|
14
|
+
#
|
15
|
+
# site - The awestruct site variable
|
16
|
+
def execute site
|
17
|
+
site.pages.each do |page|
|
18
|
+
if page.content_syntax =~ /^a(sc)?(ii)?(d(oc)?)?$/
|
19
|
+
sections = Asciidoctor.load(page.raw_content).sections
|
20
|
+
sections.each do |s|
|
21
|
+
r = String.new
|
22
|
+
s.blocks.each {|b| r << b.render}
|
23
|
+
page.send "#{s.id}=", r
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'open3'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Aweplug
|
5
|
+
module Helper
|
6
|
+
module Git
|
7
|
+
module Commit
|
8
|
+
module Metadata
|
9
|
+
# Public: Retrieves commit information from the git repo containing the file.
|
10
|
+
#
|
11
|
+
# repo_root - The directory (relative to the site base) containing the git repo
|
12
|
+
# file_path - Path to the file being processed, relative to the site base
|
13
|
+
#
|
14
|
+
# Returns an array of commit info as json values
|
15
|
+
def commit_info(repo_root, file_path)
|
16
|
+
o, _ = Open3.capture2(%Q[git --git-dir=#{repo_root}/.git log --date=iso --format='{"author":"%an","date":"%ai"}' -- #{file_path.to_s.sub(/#{repo_root}\//, '')}])
|
17
|
+
o.split("\n").map{ |l| JSON.parse l, :symbolize_names => true }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'kramdown'
|
2
|
+
require 'kramdown/parser/kramdown'
|
3
|
+
|
4
|
+
module Kramdown
|
5
|
+
module Parser
|
6
|
+
class QuickStartParser < Kramdown::Parser::Kramdown
|
7
|
+
def initialize source, options
|
8
|
+
super
|
9
|
+
@block_parsers.unshift :author_metadata
|
10
|
+
@block_parsers.unshift :level_metadata
|
11
|
+
@block_parsers.unshift :technologies_metadata
|
12
|
+
@block_parsers.unshift :target_product_metadata
|
13
|
+
@block_parsers.unshift :source_metadata
|
14
|
+
@block_parsers.unshift :summary_metadata
|
15
|
+
|
16
|
+
@root.options[:metadata] = {:author => '', :level => '',
|
17
|
+
:technologies => '', :target_product => '',
|
18
|
+
:source => '', :summary => ''}
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse_author_metadata
|
22
|
+
@src.pos += @src.matched_size
|
23
|
+
@root.options[:metadata][:author] = @src[3]
|
24
|
+
end
|
25
|
+
define_parser(:author_metadata, /^(Author:)(\s+)(.*?)$/)
|
26
|
+
|
27
|
+
def parse_level_metadata
|
28
|
+
@src.pos += @src.matched_size
|
29
|
+
@root.options[:metadata][:level] = @src[3]
|
30
|
+
end
|
31
|
+
define_parser(:level_metadata, /^(Level:)(\s+)(.*?)$/)
|
32
|
+
|
33
|
+
def parse_technologies_metadata
|
34
|
+
@src.pos += @src.matched_size
|
35
|
+
@root.options[:metadata][:technologies] = @src[3]
|
36
|
+
end
|
37
|
+
define_parser(:technologies_metadata, /^(Technologies:)(\s+)(.*?)$/)
|
38
|
+
|
39
|
+
def parse_target_product_metadata
|
40
|
+
@src.pos += @src.matched_size
|
41
|
+
@root.options[:metadata][:target_product] = @src[3]
|
42
|
+
end
|
43
|
+
define_parser(:target_product_metadata, /^(Target Product:)(\s+)(.*?)$/)
|
44
|
+
|
45
|
+
def parse_source_metadata
|
46
|
+
@src.pos += @src.matched_size
|
47
|
+
@root.options[:metadata][:source] = @src[3][1..-2]
|
48
|
+
end
|
49
|
+
define_parser(:source_metadata, /^(Source:)(\s+)(.*?)$/)
|
50
|
+
|
51
|
+
def parse_summary_metadata
|
52
|
+
@src.pos += @src.matched_size
|
53
|
+
@root.options[:metadata][:summary] = @src[3]
|
54
|
+
end
|
55
|
+
define_parser(:summary_metadata, /^(Summary:)(\s+)(.*?)$/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
File without changes
|
data/lib/aweplug.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Identity Collector' do
|
4
|
+
|
5
|
+
it 'may have one or more crawlers' do
|
6
|
+
pending "Not implemented"
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'must have one storage' do
|
10
|
+
pending "Not implemented"
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'may be configurable via a block' do
|
14
|
+
pending "Not implemented"
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'may be configured via method calls' do
|
18
|
+
pending "Not implemented"
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'must respond to execute(site)' do
|
22
|
+
pending "Not implemented"
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Storage' do
|
4
|
+
|
5
|
+
it 'must respond to write' do
|
6
|
+
pending "Not implemented"
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'must respond to read' do
|
10
|
+
pending "Not implemented"
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'must respond to fetch' do
|
14
|
+
pending "Not implemented"
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'must respond to exist' do
|
18
|
+
pending "Not implemented"
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'must respond to delete' do
|
22
|
+
pending "Not implemented"
|
23
|
+
end
|
24
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
|
3
|
+
Dir["./spec/support/**/*.rb"].sort.each {|f| require f}
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
7
|
+
config.run_all_when_everything_filtered = true
|
8
|
+
config.filter_run :focus
|
9
|
+
|
10
|
+
config.order = 'random'
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
shared_examples_for 'a crawler' do
|
2
|
+
it 'may require authentication' do
|
3
|
+
if crawler.respond_to? :authenticate_using, false
|
4
|
+
expect { crawler.crawl }.to raise_error
|
5
|
+
else
|
6
|
+
expect { crawler.crawl }.to_not raise_error
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'must respond to crawl' do
|
11
|
+
should respond_to(:crawl)
|
12
|
+
end
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: aweplug
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.a2
|
5
|
+
prerelease: 6
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- LightGuard
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-12-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: octokit
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.24.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.24.0
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: faraday
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.8.7
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.8.7
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: faraday_middleware
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.9.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.9.0
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: guard-rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ~>
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 3.0.0
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ~>
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 3.0.0
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rake
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 10.0.4
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 10.0.4
|
94
|
+
description: A set of Awestruct extensions for building a project website
|
95
|
+
email:
|
96
|
+
- lightguard.jp@gmail.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- .rspec
|
103
|
+
- Gemfile
|
104
|
+
- Guardfile
|
105
|
+
- LICENSE.txt
|
106
|
+
- README.adoc
|
107
|
+
- README.md
|
108
|
+
- Rakefile
|
109
|
+
- aweplug.gemspec
|
110
|
+
- lib/aweplug.rb
|
111
|
+
- lib/aweplug/extensions/identities.rb
|
112
|
+
- lib/aweplug/extensions/identity/confluence.rb
|
113
|
+
- lib/aweplug/extensions/identity/github.rb
|
114
|
+
- lib/aweplug/extensions/identity/gravatar.rb
|
115
|
+
- lib/aweplug/extensions/identity/jbosscommunity.rb
|
116
|
+
- lib/aweplug/extensions/kramdown_quickstart.rb
|
117
|
+
- lib/aweplug/extensions/sections.rb
|
118
|
+
- lib/aweplug/helpers/.gitkeep
|
119
|
+
- lib/aweplug/helpers/git_commit_metadata.rb
|
120
|
+
- lib/aweplug/helpers/kramdown_metadata.rb
|
121
|
+
- lib/aweplug/transformers/.gitkeep
|
122
|
+
- lib/aweplug/version.rb
|
123
|
+
- spec/aweplug/extensions/identity/collector_spec.rb
|
124
|
+
- spec/aweplug/extensions/identity/github_spec.rb
|
125
|
+
- spec/aweplug/extensions/identity/storage_spec.rb
|
126
|
+
- spec/spec_helper.rb
|
127
|
+
- spec/support/aweplug/extensions/identity/crawler_examples.rb
|
128
|
+
homepage: https://github.com/awestruct/aweplug
|
129
|
+
licenses: []
|
130
|
+
post_install_message:
|
131
|
+
rdoc_options: []
|
132
|
+
require_paths:
|
133
|
+
- lib
|
134
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ! '>='
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
141
|
+
none: false
|
142
|
+
requirements:
|
143
|
+
- - ! '>'
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 1.3.1
|
146
|
+
requirements: []
|
147
|
+
rubyforge_project:
|
148
|
+
rubygems_version: 1.8.25
|
149
|
+
signing_key:
|
150
|
+
specification_version: 3
|
151
|
+
summary: This set of Awestruct extensions includes helpful tools, extensions and
|
152
|
+
helpers for building a website using Awestruct. It includes extensions for accessing
|
153
|
+
Github, JIRA, managing identities and others.
|
154
|
+
test_files:
|
155
|
+
- spec/aweplug/extensions/identity/collector_spec.rb
|
156
|
+
- spec/aweplug/extensions/identity/github_spec.rb
|
157
|
+
- spec/aweplug/extensions/identity/storage_spec.rb
|
158
|
+
- spec/spec_helper.rb
|
159
|
+
- spec/support/aweplug/extensions/identity/crawler_examples.rb
|
160
|
+
has_rdoc:
|