forkreadme 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  Gemfile.lock
2
+ *.gem
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Adam Mckaig
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.md ADDED
@@ -0,0 +1,34 @@
1
+ This is a command-line utility for generating READMEs for GitHub forks.
2
+
3
+ I have quite a few forks of popular repos which contain no useful indication of
4
+ why they exist. Mostly they're hanging around waiting for a pull request to be
5
+ merged into or rejected from the upstream repo. And since my changes are tucked
6
+ away in feature branches, it's not immediately obvious to visitors (or me) why I
7
+ created the fork, what I changed, and whether those changes have been merged
8
+ upstream.
9
+
10
+ My solution is to replace the `README.md` in the master branch of my fork with a
11
+ note detailing what and why.
12
+ This tool does that automatically.
13
+
14
+
15
+ ## Usage
16
+
17
+ ```bash
18
+ $ gem install forkreadme
19
+ $ forkreadme generate
20
+ ```
21
+
22
+ Here's an [example of the output] [example].
23
+
24
+
25
+ ## License
26
+
27
+ [Fork README] [repo] is available under the [MIT license] [license].
28
+
29
+
30
+
31
+
32
+ [repo]: https://github.com/adammck/forkreadme
33
+ [license]: https://raw.github.com/adammck/forkreadme/master/LICENSE
34
+ [example]: https://github.com/adammck/grit
data/bin/forkreadme CHANGED
@@ -2,24 +2,29 @@
2
2
  # vim: et ts=2 sw=2
3
3
 
4
4
  require "forkreadme"
5
- require "thor"
6
-
7
- module ForkReadme
8
- class App < Thor
9
-
10
- desc "generate [DIR]", "Generate a README for a GitHub fork repo"
11
- method_option :path, :default=>"."
12
- def generate path=""
13
- begin
14
- dir = File.expand_path path, Dir.pwd
15
- puts Generator.new(dir).readme
16
-
17
- rescue ForkReadme::Error => err
18
- $stderr.puts err
19
- exit false
20
- end
21
- end
22
- end
5
+ require "trollop"
6
+
7
+ BANNER = <<EOT
8
+ ForkReadme generates a README.md for GitHub forks, containing a list of the pull requests submitted upstream.
9
+
10
+ Usage:
11
+ forkreadme [options] [path]
12
+
13
+ Options:
14
+ EOT
15
+
16
+ opts = Trollop::options do
17
+ banner BANNER
18
+ opt :pullstatus, "Include pullstat.us images", :short=>"i", :type=>:bool, :default=>true
23
19
  end
24
20
 
25
- ForkReadme::App.start
21
+ path = ARGV.shift || "."
22
+
23
+ begin
24
+ dir = File.expand_path path, Dir.pwd
25
+ puts ForkReadme::Generator.new(dir, opts[:pullstatus]).readme
26
+
27
+ rescue ForkReadme::Error => err
28
+ $stderr.puts err
29
+ exit false
30
+ end
data/forkreadme.gemspec CHANGED
@@ -6,13 +6,14 @@ require File.expand_path("../lib/forkreadme/version", __FILE__)
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "forkreadme"
8
8
  gem.version = ForkReadme::VERSION
9
+ gem.license = "MIT"
9
10
 
10
11
  gem.authors = ["Adam Mckaig"]
11
12
  gem.email = ["adam.mckaig@gmail.com"]
12
13
  gem.summary = %q{Generate useful READMEs for GitHub forks}
13
14
  gem.homepage = "https://github.com/adammck/forkreadme"
14
15
 
15
- gem.add_dependency "thor", "~> 0.14.6"
16
+ gem.add_dependency "trollop", "~> 1.16.2"
16
17
  gem.add_dependency "octokit", "~> 1.0.2"
17
18
 
18
19
  gem.files = `git ls-files`.split($\)
@@ -4,10 +4,13 @@
4
4
  module ForkReadme
5
5
  class Error < StandardError
6
6
  end
7
-
8
- class NotRepo < Error
7
+
8
+ class NotGitRepo < Error
9
+ end
10
+
11
+ class NotGitHubRepo < Error
9
12
  end
10
-
13
+
11
14
  class NotFork < Error
12
15
  end
13
16
  end
@@ -8,56 +8,83 @@ module ForkReadme
8
8
  class Generator
9
9
  include URI::REGEXP::PATTERN
10
10
 
11
- def initialize dir
12
- @dir = dir
11
+ def initialize path, with_images
12
+ @path = path
13
+ @with_images = with_images
14
+
15
+ repo_name = github_repo_name @path
16
+ @repo = octokit.repo repo_name
17
+ @parent = parent_of @repo
13
18
  end
14
19
 
15
20
  def readme
16
- repo_name = github_repo_name @dir
21
+ intro + "\n\n" + (links.join "\n")
22
+ end
17
23
 
18
- if repo_name.empty?
19
- raise NotRepo.new "Not a GitHub repo: #{@dir}"
20
- end
24
+ # Public: Returns the introduction paragraph.
25
+ def intro
26
+ link = link_to(@parent.name, @parent.html_url)
27
+ "This is a fork of #{link}, with pull requests:"
28
+ end
21
29
 
22
- repo = octokit.repo repo_name
30
+ # Public: Returns a paragraph summarizing the pull requests.
31
+ def links
32
+ pull_requests(@parent).select do |pull|
33
+ pull.head.repo.id == @repo.id
23
34
 
24
- unless repo.fork
25
- raise NotFork.new "Not a GitHub fork: #{repo_name}"
35
+ end.map do |pull|
36
+ "* " + line_for(pull, @with_images)
26
37
  end
38
+ end
27
39
 
28
- parent_name = full_name repo.parent
29
- parent = octokit.repo parent_name
30
-
31
- s = []
32
- s << "This is a fork of [#{parent.name}] (#{parent.html_url}), with pull requests:"
33
- s << ""
40
+ private
34
41
 
35
- logins = collaborator_logins repo
36
- my_pulls = pull_requests(parent).select do |pull|
37
- pull.user and logins.include?(pull.user.login)
42
+ # Private: Returns a line of Markdown summarizing a pull request.
43
+ def line_for pull_request, with_images
44
+ img = if with_images
45
+ image "Status of ##{pull_request.number}", status_image(pull_request)
38
46
  end
39
47
 
40
- my_pulls.each do |short_pull|
41
- pull = pull_request(parent, short_pull.number)
42
- if repo_name == full_name(pull.head.repo)
43
- s << " * [#{pull.title}] (#{pull.html_url})"
44
- end
48
+ suffix = img ? (" " + img) : ""
49
+ link_to(pull_request.title, pull_request.html_url) + suffix
50
+ end
51
+
52
+ # Private: Returns the parent repo (as an Octokit repo) of an Octokit repo,
53
+ # or raises NotFork if the repo does not have a parent.
54
+ def parent_of child_repo
55
+ if child_repo.parent
56
+ parent_repo_name = full_name child_repo.parent
57
+ octokit.repo parent_repo_name
58
+ else
59
+ child_name = full_name child_repo
60
+ raise NotFork.new "Not a GitHub fork: #{child_name}"
45
61
  end
62
+ end
46
63
 
47
- s.join "\n"
64
+ # Private: Returns a link in Markdown format.
65
+ def link_to text, href
66
+ "[#{text}] (#{href})"
48
67
  end
49
-
50
-
51
- private
52
-
53
- # Private: Returns an Array containing the logins of all collaborators for an
54
- # Octokit repo.
68
+
69
+ # Private: Returns an image in Markdown format.
70
+ def image alt_text, href
71
+ "!" + link_to(alt_text, href)
72
+ end
73
+
74
+ # Private: Returns an Array containing the logins of all collaborators for
75
+ # an Octokit repo.
55
76
  def collaborator_logins repo
56
77
  octokit.collabs(full_name repo).map do |user|
57
78
  user.login
58
79
  end
59
80
  end
60
-
81
+
82
+ # Private: Returns the URL of the status image (via pullstat.us) for an
83
+ # Octokit pull request.
84
+ def status_image pull_request
85
+ pull_request.html_url.sub "github.com", "pullstat.us"
86
+ end
87
+
61
88
  # Private: Returns all pull request summaries (as returned by the "List pull
62
89
  # requests" API, and wrapped by Octokit) for an Octokit repo.
63
90
  def pull_requests repo
@@ -68,16 +95,16 @@ module ForkReadme
68
95
  end
69
96
  end
70
97
 
71
- # Private: Return full pull request (as returned by the "Get a single pull
72
- # request" API, and wrapped by Octokit) to an Octokit repo and pull number.
73
- def pull_request repo, number
74
- octokit.pull full_name(repo), number
75
- end
76
-
77
- # Private: Returns the full GitHub repo name of a Git working directory.
98
+ # Private: Returns the full GitHub repo name (e.g. adammck/forkreadme) of a
99
+ # Git working directory, or raises NotGitHubRepo.
78
100
  def github_repo_name path
79
101
  clone_url = parse_url remote_url path
80
- chop_extension clone_url.path
102
+
103
+ if clone_url.host.downcase != "github.com"
104
+ raise NotGitHubRepo.new "Not a GitHub repo: #{path}"
105
+ end
106
+
107
+ chop_extension chop_leading_slash clone_url.path
81
108
  end
82
109
 
83
110
  # Private: Returns the full GitHub repo name of an Octokit repo.
@@ -90,8 +117,13 @@ module ForkReadme
90
117
  @ok ||= Octokit.new(:auto_traversal=>true)
91
118
  end
92
119
 
93
- # Private: Returns the remote url of a Git working directory.
120
+ # Private: Returns the remote clone URL of a Git working directory, or
121
+ # raises NotGitRepo.
94
122
  def remote_url path
123
+ unless is_working_dir path
124
+ raise NotGitRepo.new "Not a Git repo: #{path}"
125
+ end
126
+
95
127
  %x{git config --file #{path}/.git/config --get remote.origin.url}
96
128
  end
97
129
 
@@ -103,17 +135,27 @@ module ForkReadme
103
135
 
104
136
  rescue URI::InvalidURIError
105
137
  if m = url.match("^(#{USERINFO})@(#{HOST}):(#{REL_PATH})$")
106
- URI::Generic.new "ssh", m[1], m[2], 22, nil, m[3], nil, nil, nil
138
+ URI::Generic.new "ssh", m[1], m[2], 22, nil, "/" + m[3], nil, nil, nil
107
139
 
108
140
  else
109
141
  raise
110
142
  end
111
143
  end
112
144
  end
113
-
145
+
146
+ # Private: Return true if +path+ is a Git working directory.
147
+ def is_working_dir path
148
+ File.exist? File.expand_path ".git", path
149
+ end
150
+
114
151
  # Private: Returns a filename with the extension removed.
115
152
  def chop_extension filename
116
153
  filename.sub /\.\w+$/, ""
117
154
  end
155
+
156
+ # Private: Returns a filename with the leading slash removed.
157
+ def chop_leading_slash filename
158
+ filename.sub /^\//, ""
159
+ end
118
160
  end
119
161
  end
@@ -2,5 +2,5 @@
2
2
  # vim: et ts=2 sw=2
3
3
 
4
4
  module ForkReadme
5
- VERSION = "0.0.1"
5
+ VERSION = "0.0.2"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forkreadme
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,27 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-26 00:00:00.000000000 Z
12
+ date: 2012-05-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: thor
16
- requirement: &70204084253700 !ruby/object:Gem::Requirement
15
+ name: trollop
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 0.14.6
21
+ version: 1.16.2
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70204084253700
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.16.2
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: octokit
27
- requirement: &70204084253100 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,7 +37,12 @@ dependencies:
32
37
  version: 1.0.2
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *70204084253100
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.2
36
46
  description:
37
47
  email:
38
48
  - adam.mckaig@gmail.com
@@ -43,6 +53,8 @@ extra_rdoc_files: []
43
53
  files:
44
54
  - .gitignore
45
55
  - Gemfile
56
+ - LICENSE
57
+ - README.md
46
58
  - bin/forkreadme
47
59
  - forkreadme.gemspec
48
60
  - lib/forkreadme.rb
@@ -50,7 +62,8 @@ files:
50
62
  - lib/forkreadme/generator.rb
51
63
  - lib/forkreadme/version.rb
52
64
  homepage: https://github.com/adammck/forkreadme
53
- licenses: []
65
+ licenses:
66
+ - MIT
54
67
  post_install_message:
55
68
  rdoc_options: []
56
69
  require_paths:
@@ -69,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
82
  version: '0'
70
83
  requirements: []
71
84
  rubyforge_project:
72
- rubygems_version: 1.8.15
85
+ rubygems_version: 1.8.23
73
86
  signing_key:
74
87
  specification_version: 3
75
88
  summary: Generate useful READMEs for GitHub forks