Fingertips-jewelry_portfolio 0.2.3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Fingertips, Eloy Duran <eloy.de.enige@gmail.com>, Thijs van der Vossen <thijs@fngtps.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc CHANGED
@@ -1,124 +1,106 @@
1
- = JewelryPortfolio
1
+ = Jewelry Portfolio
2
2
 
3
- Surely also lazy developers like to showcase their jewelry portfolio on their
4
- GitHub pages.
3
+ <em>Surely also lazy developers like to showcase their jewelry portfolio on
4
+ their GitHub pages.</em>
5
5
 
6
- Imagine writing an erb template once and use <tt>rake release</tt> to release
7
- your gem with Jeweler as usual, but in addition re-generate and push the
8
- index.html for your GitHub pages. If that sounds good to you, you're in luck.
9
- Because that's exactly what this add-on for
10
- Jeweler[http://github.com/technicalpickles/jeweler/tree/master] does.
6
+ Imagine writing a template once and use <tt>rake portfolio:release</tt>
7
+ to generate and push an index.html and feed.xml file to your GitHub pages
8
+ repository containing all the repositories you want to. If that sounds good to
9
+ you, you're in luck. Because that's exactly what this gem does.
11
10
 
12
- == Usage
11
+ Note that if you have a <tt>rake release</tt> task, then the <tt>rake
12
+ portfolio:release</tt> task is automatically invoked after the original
13
+ finishes. An example of a Gem which provides such a task is
14
+ Jeweler[http://github.com/technicalpickles/jeweler/tree/master].
13
15
 
14
- === GitHub pages repository
16
+ == Installation
15
17
 
16
- First things first; create a GitHub pages repository if you haven't done so
17
- already. See http://github.com/guides/pages for more info.
18
+ Run the following if you haven't done so before:
18
19
 
19
- Then create the following files, and content, in the master branch of your
20
- pages repository (<em>for a more elaborate example see:
21
- http://github.com/alloy/alloy.github.com/tree/master</em>):
20
+ gem sources -a http://gems.github.com
22
21
 
23
- * <b>Rakefile:</b>
22
+ Install the gem:
24
23
 
25
- require 'jewelry_portfolio/tasks'
26
- JewelryPortfolio::Tasks.new do |t|
27
- t.account = 'Fingertips'
28
- t.name = 'passengerpane'
29
- t.version = '1.2.0'
30
- t.summary = 'A short summary about the project.'
31
- t.description = 'A longer description about the project.'
32
- end
24
+ sudo gem install Fingertips-jewelry_portfolio
33
25
 
34
- The +account+ is only necessary when you haven't configured github.user in
35
- the local or global git config. (For more info see:
36
- http://github.com/guides/local-github-config.) Or if you want to override the
37
- +account+ that was retrieved from the git config.
38
-
39
- The other attributes are only necessary when there's no gemspec file in the
40
- work directory.
26
+ == GitHub pages repository
41
27
 
42
- * <b>template.html.erb:</b>
43
-
44
- This is the main template file which will be used to generate the index.html
45
- file. All repositories and their gem specifications are available as the
46
- local variable <tt>repos</tt>. See JewelryPortfolio::Template and
47
- JewelryPortfolio::Repo for more information.</em>.
28
+ First things first; create a GitHub pages repository if you haven't done so
29
+ already. See http://github.com/guides/pages for more info.
48
30
 
49
- <html>
50
- <head>
51
- <title>Alloy&rsquo;s jewelry</title>
52
- </head>
31
+ Then you can merge the code from our Fingertips pages repository as an example
32
+ on how to create your index.html and feed.xml files:
53
33
 
54
- <p>This is an overview of the available gems by Eloy Duran, aka `alloy'.</p>
34
+ $ git remote add fingertips git://github.com/Fingertips/fingertips.github.com.git
35
+ $ git fetch fingertips
36
+ $ git merge fingertips/master
55
37
 
56
- <body>
57
- <% repos.each do |repo| %>
58
- <%= repo_partial(repo) %>
59
- <% end %>
60
- </body>
61
- </html>
38
+ Update the Rakefile to use the correct account, or none if it can be inflected
39
+ from the <tt>github.user</tt> value of your local or global git config. For
40
+ more info see: http://github.com/guides/local-github-config.
62
41
 
63
- * <b>repo.html.erb:</b>
42
+ For more information on the template renderers see:
43
+ JewelryPortfolio::Template::HTML and JewelryPortfolio::Template::Feed.
64
44
 
65
- This file is completely optional; it's just a showcase of using a repo
66
- partial.
45
+ If you want to add repos by hand then take a look at <tt>repos.yml</tt>. When
46
+ done remove it so you have a fresh state:
67
47
 
68
- <div>
69
- <h1><a href="<%= repo.url %>"><%= spec.name %> <%= spec.version %></a></h1>
70
- <p><%= spec.description %></p>
71
- <p>Install: <code>$ <%= repo.gem_install_command %></code></p>
72
- <p>Clone: <code>$ git clone <%= repo.clone_url %></code></p>
73
- </div>
48
+ $ git rm repos.yml
49
+ $ git commit -a -m "Reset repos.yml state"
74
50
 
75
- Now you can generate the index.html file with:
51
+ Now you can generate the index.html and feed.xml files with:
76
52
 
77
53
  $ rake portfolio:generate
78
54
 
79
- Since you haven't added any projects yet the generated index will be pretty
80
- dull. But for now just release this version:
55
+ And generate, commit and push to the remote branch with:
81
56
 
82
57
  $ rake portfolio:release
83
58
 
84
- Whenever you update the template you can use these tasks to preview and/or
59
+ Whenever you update the templates you can use these tasks to preview and/or
85
60
  release it.
86
61
 
87
- === Add super-cow powers to your project's Rakefile
62
+ == Using in a non-Gem project
88
63
 
89
- Update the Rakefile of the project that you would like to include in your
90
- jewelry portfolio like so:
64
+ In your Rakefile instantiate a JewelryPortfolio::Tasks object, and give it a
65
+ block with details about your project:
91
66
 
92
67
  begin
93
- require 'jeweler'
94
- Jeweler::Tasks.new do |s|
95
- # ...
96
- end
97
-
98
- # Add the following to your Rakefile to use JewelryPortfolio
99
- begin
100
- require 'jewelry_portfolio/tasks'
101
- JewelryPortfolio::Tasks.new do |t|
102
- # Only specify the account if it's different from `github.user' in the git config.
103
- t.account = 'Fingertips'
104
- end
105
- rescue LoadError
106
- puts "JewelryPortfolio not available. Install it with: sudo gem install Fingertips-jewelry_portfolio -s http://gems.github.com"
68
+ require 'jewelry_portfolio/tasks'
69
+ JewelryPortfolio::Tasks.new do |p|
70
+ # p.account = 'Fingertips'
71
+ p.name = 'jewelry_portfolio'
72
+ p.version = '1.0.0'
73
+ p.summary = 'Short summary about the project.'
74
+ p.description = 'Long description about the project.'
107
75
  end
108
-
109
76
  rescue LoadError
110
- puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
77
+ puts "JewelryPortfolio not available. Install it with: sudo gem install Fingertips-jewelry_portfolio -s http://gems.github.com"
111
78
  end
112
79
 
113
- From now on, whenever you use the +release+ rake task, the GitHub pages
114
- index.html will be re-generated and pushed to GitHub after releasing the gem.
80
+ In this example +p+ is a JewelryPortfolio::Repo instance. See its reference for
81
+ details about the available options.
82
+
83
+ Note that the +account+ value should _only_ be set if it can't be inflected
84
+ from the <tt>github.user</tt> value of your local or global git config. For
85
+ more info see: http://github.com/guides/local-github-config.
86
+
87
+ For generating and releasing the portfolio, use the aforementioned
88
+ <tt>portfolio:generate</tt> and <tt>portfolio:release</tt> rake tasks.
89
+
90
+ == Using in a Gem project
91
+
92
+ If your project contains a gemspec file, then not much configuration is needed
93
+ because all values will be copied from it. Simply add the following to your
94
+ Rakefile:
95
+
96
+ require 'jewelry_portfolio/tasks'
97
+ JewelryPortfolio::Tasks.new
115
98
 
116
- If you just want to re-generate, or release, the jewelry portfolio use the
117
- aforementioned <tt>portfolio:generate</tt> and <tt>portfolio:release</tt> rake
118
- tasks.
99
+ You can override the attributes as described in ‘Using in a non-Gem project’.
119
100
 
120
- Note that it isn't necessary to use Jeweler to be able to use JewelryPortfolio.
101
+ For generating and releasing the portfolio, use the aforementioned
102
+ <tt>portfolio:generate</tt> and <tt>portfolio:release</tt> rake tasks.
121
103
 
122
104
  == COPYRIGHT
123
105
 
124
- Copyright (c) 2009 Fingertips, Eloy Duran. See LICENSE for details.
106
+ Copyright © 2009 Fingertips, Eloy Duran, Thijs van der Vossen. See LICENSE for details.
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
+ :minor: 3
3
+ :patch: 0
2
4
  :major: 0
3
- :minor: 2
4
- :patch: 3
@@ -3,9 +3,7 @@ require 'jewelry_portfolio/repos_index'
3
3
  require 'jewelry_portfolio/template'
4
4
 
5
5
  class JewelryPortfolio
6
- class FileMissingError < StandardError; end
7
-
8
- attr_reader :account, :repo, :index, :template
6
+ attr_reader :account, :repo, :index, :html_template, :feed_template
9
7
 
10
8
  # Initializes a JewelryPortfolio instance for the specified +account+.
11
9
  #
@@ -17,18 +15,20 @@ class JewelryPortfolio
17
15
  raise ArgumentError, "No `account' given." unless account
18
16
  raise ArgumentError, "No valid `repo' given." if repo && !repo.valid?
19
17
 
20
- @account = account
21
- @repo = repo
22
- @index = ReposIndex.new(@account, (Dir.pwd unless @repo))
23
- @template = Template.new(File.join(@index.path, 'template'), @index.repos)
18
+ @account = account
19
+ @repo = repo
20
+ @index = ReposIndex.new(@account, (Dir.pwd unless @repo))
21
+
22
+ @html_template = template(Template::HTML, 'index.erb')
23
+ @feed_template = template(Template::Feed, 'feed.rb')
24
24
 
25
25
  @index.add(@repo) if @repo
26
26
  end
27
27
 
28
28
  # Renders the index.html file.
29
29
  def render!
30
- puts "Generating html"
31
- File.open(File.join(@index.path, 'index.html'), 'w') { |f| f << @template.render }
30
+ write_out('HTML', 'index.html', @html_template.render)
31
+ write_out('feed', 'feed.xml', @feed_template.render)
32
32
  end
33
33
 
34
34
  # Renders the index.html file, then commits and pushes it to the remote.
@@ -40,6 +40,15 @@ class JewelryPortfolio
40
40
 
41
41
  private
42
42
 
43
+ def template(klass, file)
44
+ klass.new(File.join(@index.path, file), @account, @index.repos)
45
+ end
46
+
47
+ def write_out(message, file, data)
48
+ puts "Generating #{message}"
49
+ File.open(File.join(@index.path, file), 'w') { |f| f << data }
50
+ end
51
+
43
52
  def commit_message
44
53
  if @repo
45
54
  "Updated github pages for: #{@repo.name}-#{@repo.version}"
@@ -25,13 +25,21 @@ class JewelryPortfolio
25
25
  # Not needed when initialized with a Gem::Specification.
26
26
  attr_accessor :description
27
27
 
28
+ # The Time at which this Repo was last updated.
29
+ attr_reader :updated_at
30
+
28
31
  def initialize(account = nil, spec = nil)
29
32
  @account = account
30
33
  @gem = !spec.nil?
31
34
 
32
- %w{ name version summary description }.each do |attr|
33
- send("#{attr}=", spec.send(attr).to_s)
34
- end if spec
35
+ if spec
36
+ @updated_at = Time.utc(spec.date.year, spec.date.month, spec.date.day)
37
+ %w{ name version summary description }.each do |attr|
38
+ send("#{attr}=", spec.send(attr).to_s)
39
+ end
40
+ end
41
+
42
+ @updated_at = Time.now unless @updated_at
35
43
  end
36
44
 
37
45
  # Returns whether or not there's a Ruby gem for this repo.
@@ -70,6 +78,14 @@ class JewelryPortfolio
70
78
  @name.hash
71
79
  end
72
80
 
81
+ def <=>(other)
82
+ if (res = @updated_at <=> other.updated_at) != 0
83
+ res
84
+ else
85
+ @version.split('.') <=> other.version.split('.')
86
+ end
87
+ end
88
+
73
89
  def ==(other)
74
90
  other.is_a?(Repo) && hash == other.hash
75
91
  end
@@ -84,6 +84,7 @@ class JewelryPortfolio
84
84
  @pages_repo = Git.open(path)
85
85
  unless @custom_work_directory
86
86
  puts "Pulling `#{url}'"
87
+ @pages_repo.checkout('.')
87
88
  @pages_repo.checkout('master')
88
89
  @pages_repo.fetch('origin')
89
90
  @pages_repo.merge('origin/master')
@@ -1,69 +1,43 @@
1
- require 'erb'
1
+ require 'jewelry_portfolio/template/feed'
2
+ require 'jewelry_portfolio/template/html'
2
3
 
3
4
  class JewelryPortfolio
4
5
  # This class is responsible for rendering a template.
5
6
  class Template
7
+ class FileMissingError < StandardError; end
8
+ class NotImplemented < StandardError; end
9
+
6
10
  # The full path to the template file.
7
- attr_reader :template
11
+ attr_reader :file
8
12
 
9
13
  # The directory in which the template resides.
10
14
  attr_reader :view_path
11
15
 
16
+ # The account name on GitHub.
17
+ attr_reader :account
18
+
12
19
  # The array of JewelryPortfolio::Repo instances.
13
20
  attr_reader :repos
14
21
 
15
22
  # Initialize with the path to the +template+, minus the extensions, and an
16
23
  # array of JewelryPortfolio::Repo instances as +repos+.
17
- def initialize(template, repos)
18
- template = File.expand_path(template)
19
- @view_path = File.dirname(template)
20
- @template = html_template_file(File.basename(template))
24
+ def initialize(template_file, account, repos)
25
+ @file = template_file
26
+ verify_template!
27
+
28
+ @view_path = File.dirname(@file)
29
+ @account = account
21
30
  @repos = repos.to_a
22
31
  end
23
32
 
24
- # Renders the template and returns the output.
25
33
  def render
26
- erb @template, binding
27
- end
28
-
29
- # Renders a partial specified by +partial_name+ minus the extension. You
30
- # can optionally specify a hash of +local_variables+ which will be
31
- # available while rendering the partial.
32
- #
33
- # Consider a partial named <tt>foo.html.erb</tt>, in the same directory as
34
- # the template, containing the following:
35
- #
36
- # Text: <%= text %>
37
- #
38
- # This partial can now be rendered like this:
39
- #
40
- # partial('foo', :text => 'bar') # => "Text: bar"
41
- def partial(partial_name, local_variables = {})
42
- for (var_name, var_value) in local_variables
43
- eval "#{var_name} = var_value"
44
- end
45
- erb html_template_file(partial_name), binding
46
- end
47
-
48
- # Renders a partial for the specified +repo+. This method looks for a
49
- # partial file named <tt>repo.html.erb</tt> in the same directory as the
50
- # template.
51
- #
52
- # See partial for more info.
53
- def repo_partial(repo, local_variables = {})
54
- partial 'repo', local_variables.merge(:repo => repo)
34
+ raise NotImplemented, 'Needs to be implemented by the subclass.'
55
35
  end
56
36
 
57
37
  private
58
38
 
59
- def erb(file, binding)
60
- ERB.new(File.read(file)).result(binding)
61
- end
62
-
63
- def html_template_file(name)
64
- path = File.join(view_path, "#{name}.html.erb")
65
- raise FileMissingError, "Could not find template at path `#{path}'" unless File.exist?(path)
66
- path
39
+ def verify_template!
40
+ raise FileMissingError, "Could not find template at path `#{@file}'" unless File.exist?(@file)
67
41
  end
68
42
  end
69
43
  end
@@ -0,0 +1,123 @@
1
+ require "builder"
2
+ require "rss"
3
+
4
+ class JewelryPortfolio
5
+ class Template
6
+ # This class is responsible for rendering an Atom RSS feed template.
7
+ #
8
+ # To override the title or description of the feed in your template:
9
+ #
10
+ # feed.title = 'Code from alloy'
11
+ # feed.description = 'The Ruby libraries, from alloy, available as open-source projects'
12
+ #
13
+ # To override any of the attributes generated for each repo, override the
14
+ # methods: id_for_repo, updated_for_repo, title_for_repo, link_for_repo,
15
+ # summary_for_repo, and description_for_repo:
16
+ #
17
+ # def feed.title_for_repo(repo)
18
+ # "#{repo.name.capitalize} (#{repo.version})"
19
+ # end
20
+ class Feed < Template
21
+ # The title that should be used for the feed.
22
+ #
23
+ # This defaults to <tt>"Code from #{@account}"</tt>.
24
+ attr_accessor :title
25
+
26
+ # The description (+subtitle+) that should be used for the feed.
27
+ #
28
+ # This defaults to <tt>"The Ruby libraries, from #{@account}, available
29
+ # as open-source projects"</tt>.
30
+ attr_accessor :description
31
+
32
+ def initialize(template_file, account, repos)
33
+ super
34
+ @title = "Code from #{@account}"
35
+ @description = "The Ruby libraries, from #{@account}, available as open-source projects"
36
+ load_template!
37
+ end
38
+
39
+ # Loads the template. A local variable named `feed' is made available,
40
+ # which holds a reference to this JewelryPortfolio::Template::Feed
41
+ # instance.
42
+ def load_template!
43
+ feed = self
44
+ eval(File.read(@file))
45
+ end
46
+
47
+ # Returns the repos ordered by +updated_at+ then +version+.
48
+ #
49
+ # See JewelryPortfolio::Repo#<=>
50
+ def repos
51
+ super.sort
52
+ end
53
+
54
+ # Returns the +id+ to be used for the feed.
55
+ def feed_id
56
+ "http://#{@account.downcase}.github.com/"
57
+ end
58
+
59
+ # Returns the URL to the feed.
60
+ def feed_url
61
+ "http://#{@account}.github.com/feed.xml"
62
+ end
63
+
64
+ # Returns the +id+ attribute to be used for the repo.
65
+ def id_for_repo(repo)
66
+ "#{repo.url}##{repo.version}"
67
+ end
68
+
69
+ # Returns the +updated+ attribute to be used for the repo.
70
+ def updated_for_repo(repo)
71
+ repo.updated_at.iso8601
72
+ end
73
+
74
+ # Returns the +title+ attribute to be used for the repo.
75
+ def title_for_repo(repo)
76
+ "#{repo.name} #{repo.version}"
77
+ end
78
+
79
+ # Returns the +link+ attribute to be used for the repo.
80
+ def link_for_repo(repo)
81
+ repo.url
82
+ end
83
+
84
+ # Returns the +summary+ attribute to be used for the repo.
85
+ def summary_for_repo(repo)
86
+ repo.summary
87
+ end
88
+
89
+ # Returns the +description+ attribute to be used for the repo.
90
+ def description_for_repo(repo)
91
+ repo.description
92
+ end
93
+
94
+ # Renders the HTML and returns the output.
95
+ def render(&block)
96
+ output = ''
97
+
98
+ xml = Builder::XmlMarkup.new(:target => output, :indent => 2)
99
+ xml.instruct!
100
+ xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
101
+ xml.id feed_id
102
+ xml.link "rel" => "self", "href" => feed_url
103
+ xml.updated Time.now.iso8601
104
+ xml.author { xml.name @account }
105
+
106
+ xml.title @title
107
+ xml.subtitle @description
108
+
109
+ repos.each do |repo|
110
+ xml.entry do
111
+ xml.id id_for_repo(repo)
112
+ xml.updated updated_for_repo(repo)
113
+ xml.title title_for_repo(repo)
114
+ xml.link :href => link_for_repo(repo)
115
+ xml.summary summary_for_repo(repo)
116
+ xml.content description_for_repo(repo)
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end