changelog_jira 1.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +233 -0
- data/Rakefile +39 -0
- data/bin/git-generate-changelog +4 -0
- data/bin/github_changelog_generator +4 -0
- data/lib/CHANGELOG.md +58 -0
- data/lib/github_changelog_generator.rb +41 -0
- data/lib/github_changelog_generator/fetcher.rb +221 -0
- data/lib/github_changelog_generator/generator/generator.rb +143 -0
- data/lib/github_changelog_generator/generator/generator_fetcher.rb +83 -0
- data/lib/github_changelog_generator/generator/generator_generation.rb +190 -0
- data/lib/github_changelog_generator/generator/generator_processor.rb +193 -0
- data/lib/github_changelog_generator/generator/generator_tags.rb +184 -0
- data/lib/github_changelog_generator/helper.rb +37 -0
- data/lib/github_changelog_generator/parser.rb +285 -0
- data/lib/github_changelog_generator/parser_file.rb +103 -0
- data/lib/github_changelog_generator/reader.rb +84 -0
- data/lib/github_changelog_generator/task.rb +67 -0
- data/lib/github_changelog_generator/version.rb +3 -0
- data/man/git-generate-changelog.1 +252 -0
- data/man/git-generate-changelog.html +262 -0
- data/man/git-generate-changelog.md +179 -0
- data/spec/files/angular.js.md +9395 -0
- data/spec/files/bundler.md +1911 -0
- data/spec/files/github-changelog-generator.md +305 -0
- data/spec/install-gem-in-bundler.gemfile +3 -0
- data/spec/spec_helper.rb +55 -0
- data/spec/unit/fetcher_spec.rb +59 -0
- data/spec/unit/generator/generator_processor_spec.rb +28 -0
- data/spec/unit/generator/generator_tags_spec.rb +243 -0
- data/spec/unit/parse_file_spec.rb +73 -0
- data/spec/unit/parser_spec.rb +60 -0
- data/spec/unit/reader_spec.rb +113 -0
- metadata +190 -0
@@ -0,0 +1,184 @@
|
|
1
|
+
module GitHubChangelogGenerator
|
2
|
+
class Generator
|
3
|
+
# fetch, filter tags, fetch dates and sort them in time order
|
4
|
+
def fetch_and_filter_tags
|
5
|
+
@filtered_tags = get_filtered_tags(@fetcher.get_all_tags)
|
6
|
+
fetch_tags_dates
|
7
|
+
end
|
8
|
+
|
9
|
+
# Sort all tags by date
|
10
|
+
def sort_tags_by_date(tags)
|
11
|
+
puts "Sorting tags..." if @options[:verbose]
|
12
|
+
tags.sort_by! do |x|
|
13
|
+
get_time_of_tag(x)
|
14
|
+
end.reverse!
|
15
|
+
end
|
16
|
+
|
17
|
+
# Try to find tag date in local hash.
|
18
|
+
# Otherwise fFetch tag time and put it to local hash file.
|
19
|
+
# @param [Hash] tag_name name of the tag
|
20
|
+
# @return [Time] time of specified tag
|
21
|
+
def get_time_of_tag(tag_name)
|
22
|
+
raise ChangelogGeneratorError, "tag_name is nil".red if tag_name.nil?
|
23
|
+
|
24
|
+
name_of_tag = tag_name["name"]
|
25
|
+
time_for_name = @tag_times_hash[name_of_tag]
|
26
|
+
if !time_for_name.nil?
|
27
|
+
time_for_name
|
28
|
+
else
|
29
|
+
time_string = @fetcher.fetch_date_of_tag tag_name
|
30
|
+
@tag_times_hash[name_of_tag] = time_string
|
31
|
+
time_string
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Detect link, name and time for specified tag.
|
36
|
+
#
|
37
|
+
# @param [Hash] newer_tag newer tag. Can be nil, if it's Unreleased section.
|
38
|
+
# @return [Array] link, name and time of the tag
|
39
|
+
def detect_link_tag_time(newer_tag)
|
40
|
+
# if tag is nil - set current time
|
41
|
+
newer_tag_time = newer_tag.nil? ? Time.new : get_time_of_tag(newer_tag)
|
42
|
+
|
43
|
+
# if it's future release tag - set this value
|
44
|
+
if newer_tag.nil? && @options[:future_release]
|
45
|
+
newer_tag_name = @options[:future_release]
|
46
|
+
newer_tag_link = @options[:future_release]
|
47
|
+
else
|
48
|
+
# put unreleased label if there is no name for the tag
|
49
|
+
newer_tag_name = newer_tag.nil? ? @options[:unreleased_label] : newer_tag["name"]
|
50
|
+
newer_tag_link = newer_tag.nil? ? "HEAD" : newer_tag_name
|
51
|
+
end
|
52
|
+
[newer_tag_link, newer_tag_name, newer_tag_time]
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [Object] try to find newest tag using #Reader and :base option if specified otherwise returns nil
|
56
|
+
def detect_since_tag
|
57
|
+
@since_tag ||= @options.fetch(:since_tag) { version_of_first_item }
|
58
|
+
end
|
59
|
+
|
60
|
+
def version_of_first_item
|
61
|
+
return unless File.file?(@options[:base].to_s)
|
62
|
+
|
63
|
+
sections = GitHubChangelogGenerator::Reader.new.read(@options[:base])
|
64
|
+
sections.first["version"] if sections && sections.any?
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return tags after filtering tags in lists provided by option: --between-tags & --exclude-tags
|
68
|
+
#
|
69
|
+
# @return [Array]
|
70
|
+
def get_filtered_tags(all_tags)
|
71
|
+
filtered_tags = filter_since_tag(all_tags)
|
72
|
+
filtered_tags = filter_between_tags(filtered_tags)
|
73
|
+
filter_excluded_tags(filtered_tags)
|
74
|
+
end
|
75
|
+
|
76
|
+
# @param [Array] all_tags all tags
|
77
|
+
# @return [Array] filtered tags according :since_tag option
|
78
|
+
def filter_since_tag(all_tags)
|
79
|
+
filtered_tags = all_tags
|
80
|
+
tag = detect_since_tag
|
81
|
+
if tag
|
82
|
+
if all_tags.map(&:name).include? tag
|
83
|
+
idx = all_tags.index { |t| t.name == tag }
|
84
|
+
filtered_tags = if idx > 0
|
85
|
+
all_tags[0..idx - 1]
|
86
|
+
else
|
87
|
+
[]
|
88
|
+
end
|
89
|
+
else
|
90
|
+
Helper.log.warn "Warning: can't find tag #{tag}, specified with --since-tag option."
|
91
|
+
end
|
92
|
+
end
|
93
|
+
filtered_tags
|
94
|
+
end
|
95
|
+
|
96
|
+
# @param [Array] all_tags all tags
|
97
|
+
# @return [Array] filtered tags according :due_tag option
|
98
|
+
def filter_due_tag(all_tags)
|
99
|
+
filtered_tags = all_tags
|
100
|
+
tag = @options[:due_tag]
|
101
|
+
if tag
|
102
|
+
if (all_tags.count > 0) && (all_tags.map(&:name).include? tag)
|
103
|
+
idx = all_tags.index { |t| t.name == tag }
|
104
|
+
last_index = all_tags.count - 1
|
105
|
+
filtered_tags = if idx > 0 && idx < last_index
|
106
|
+
all_tags[idx + 1..last_index]
|
107
|
+
else
|
108
|
+
[]
|
109
|
+
end
|
110
|
+
else
|
111
|
+
Helper.log.warn "Warning: can't find tag #{tag}, specified with --due-tag option."
|
112
|
+
end
|
113
|
+
end
|
114
|
+
filtered_tags
|
115
|
+
end
|
116
|
+
|
117
|
+
# @param [Array] all_tags all tags
|
118
|
+
# @return [Array] filtered tags according :between_tags option
|
119
|
+
def filter_between_tags(all_tags)
|
120
|
+
filtered_tags = all_tags
|
121
|
+
if @options[:between_tags]
|
122
|
+
@options[:between_tags].each do |tag|
|
123
|
+
unless all_tags.map(&:name).include? tag
|
124
|
+
Helper.log.warn "Warning: can't find tag #{tag}, specified with --between-tags option."
|
125
|
+
end
|
126
|
+
end
|
127
|
+
filtered_tags = all_tags.select { |tag| @options[:between_tags].include? tag.name }
|
128
|
+
end
|
129
|
+
filtered_tags
|
130
|
+
end
|
131
|
+
|
132
|
+
# @param [Array] all_tags all tags
|
133
|
+
# @return [Array] filtered tags according :exclude_tags or :exclude_tags_regex option
|
134
|
+
def filter_excluded_tags(all_tags)
|
135
|
+
if @options[:exclude_tags]
|
136
|
+
apply_exclude_tags(all_tags)
|
137
|
+
elsif @options[:exclude_tags_regex]
|
138
|
+
apply_exclude_tags_regex(all_tags)
|
139
|
+
else
|
140
|
+
all_tags
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def apply_exclude_tags(all_tags)
|
147
|
+
if @options[:exclude_tags].is_a?(Regexp)
|
148
|
+
filter_tags_with_regex(all_tags, @options[:exclude_tags])
|
149
|
+
else
|
150
|
+
filter_exact_tags(all_tags)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def apply_exclude_tags_regex(all_tags)
|
155
|
+
filter_tags_with_regex(all_tags, Regexp.new(@options[:exclude_tags_regex]))
|
156
|
+
end
|
157
|
+
|
158
|
+
def filter_tags_with_regex(all_tags, regex)
|
159
|
+
warn_if_nonmatching_regex(all_tags)
|
160
|
+
all_tags.reject { |tag| regex =~ tag.name }
|
161
|
+
end
|
162
|
+
|
163
|
+
def filter_exact_tags(all_tags)
|
164
|
+
@options[:exclude_tags].each do |tag|
|
165
|
+
warn_if_tag_not_found(all_tags, tag)
|
166
|
+
end
|
167
|
+
all_tags.reject { |tag| @options[:exclude_tags].include? tag.name }
|
168
|
+
end
|
169
|
+
|
170
|
+
def warn_if_nonmatching_regex(all_tags)
|
171
|
+
unless all_tags.map(&:name).any? { |t| @options[:exclude_tags] =~ t }
|
172
|
+
Helper.log.warn "Warning: unable to reject any tag, using regex "\
|
173
|
+
"#{@options[:exclude_tags].inspect} in --exclude-tags "\
|
174
|
+
"option."
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def warn_if_tag_not_found(all_tags, tag)
|
179
|
+
unless all_tags.map(&:name).include? tag
|
180
|
+
Helper.log.warn "Warning: can't find tag #{tag}, specified with --exclude-tags option."
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "logger"
|
2
|
+
module GitHubChangelogGenerator
|
3
|
+
module Helper
|
4
|
+
# @return true if the currently running program is a unit test
|
5
|
+
def self.test?
|
6
|
+
defined? SpecHelper
|
7
|
+
end
|
8
|
+
|
9
|
+
@log ||= if test?
|
10
|
+
Logger.new(nil) # don't show any logs when running tests
|
11
|
+
else
|
12
|
+
Logger.new(STDOUT)
|
13
|
+
end
|
14
|
+
@log.formatter = proc do |severity, _datetime, _progname, msg|
|
15
|
+
string = "#{msg}\n"
|
16
|
+
|
17
|
+
if severity == "DEBUG"
|
18
|
+
string = string.magenta
|
19
|
+
elsif severity == "INFO"
|
20
|
+
string = string.white
|
21
|
+
elsif severity == "WARN"
|
22
|
+
string = string.yellow
|
23
|
+
elsif severity == "ERROR"
|
24
|
+
string = string.red
|
25
|
+
elsif severity == "FATAL"
|
26
|
+
string = string.red.bold
|
27
|
+
end
|
28
|
+
|
29
|
+
string
|
30
|
+
end
|
31
|
+
|
32
|
+
# Logging happens using this method
|
33
|
+
class << self
|
34
|
+
attr_reader :log
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,285 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require "optparse"
|
3
|
+
require "pp"
|
4
|
+
require_relative "version"
|
5
|
+
require_relative "helper"
|
6
|
+
module GitHubChangelogGenerator
|
7
|
+
class Parser
|
8
|
+
# parse options with optparse
|
9
|
+
def self.parse_options
|
10
|
+
options = default_options
|
11
|
+
|
12
|
+
ParserFile.new(options).parse!
|
13
|
+
|
14
|
+
parser = setup_parser(options)
|
15
|
+
parser.parse!
|
16
|
+
|
17
|
+
user_and_project_from_git(options)
|
18
|
+
|
19
|
+
abort(parser.banner) unless options[:user] && options[:project]
|
20
|
+
|
21
|
+
print_options(options)
|
22
|
+
|
23
|
+
options
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param [Hash] options to display
|
27
|
+
def self.print_options(options)
|
28
|
+
if options[:verbose]
|
29
|
+
Helper.log.info "Performing task with options:"
|
30
|
+
options_to_display = options.clone
|
31
|
+
options_to_display[:token] = options_to_display[:token].nil? ? nil : "hidden value"
|
32
|
+
pp options_to_display
|
33
|
+
puts ""
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# setup parsing options
|
38
|
+
def self.setup_parser(options)
|
39
|
+
parser = OptionParser.new do |opts|
|
40
|
+
opts.banner = "Usage: github_changelog_generator [options]"
|
41
|
+
opts.on("-u", "--user [USER]", "Username of the owner of target GitHub repo") do |last|
|
42
|
+
options[:user] = last
|
43
|
+
end
|
44
|
+
opts.on("-p", "--project [PROJECT]", "Name of project on GitHub") do |last|
|
45
|
+
options[:project] = last
|
46
|
+
end
|
47
|
+
opts.on("-t", "--token [TOKEN]", "To make more than 50 requests per hour your GitHub token is required. You can generate it at: https://github.com/settings/tokens/new") do |last|
|
48
|
+
options[:token] = last
|
49
|
+
end
|
50
|
+
opts.on("-f", "--date-format [FORMAT]", "Date format. Default is %Y-%m-%d") do |last|
|
51
|
+
options[:date_format] = last
|
52
|
+
end
|
53
|
+
opts.on("-o", "--output [NAME]", "Output file. Default is CHANGELOG.md") do |last|
|
54
|
+
options[:output] = last
|
55
|
+
end
|
56
|
+
opts.on("-b", "--base [NAME]", "Optional base file to append generated changes to.") do |last|
|
57
|
+
options[:base] = last
|
58
|
+
end
|
59
|
+
opts.on("--bugs-label [LABEL]", "Setup custom label for bug-fixes section. Default is \"**Fixed bugs:**""") do |v|
|
60
|
+
options[:bug_prefix] = v
|
61
|
+
end
|
62
|
+
opts.on("--enhancement-label [LABEL]", "Setup custom label for enhancements section. Default is \"**Implemented enhancements:**\"") do |v|
|
63
|
+
options[:enhancement_prefix] = v
|
64
|
+
end
|
65
|
+
opts.on("--issues-label [LABEL]", "Setup custom label for closed-issues section. Default is \"**Closed issues:**\"") do |v|
|
66
|
+
options[:issue_prefix] = v
|
67
|
+
end
|
68
|
+
opts.on("--header-label [LABEL]", "Setup custom header label. Default is \"# Change Log\"") do |v|
|
69
|
+
options[:header] = v
|
70
|
+
end
|
71
|
+
opts.on("--front-matter [JSON]", "Add YAML front matter. Formatted as JSON because it's easier to add on the command line") do |v|
|
72
|
+
options[:frontmatter] = JSON.parse(v).to_yaml + "---\n"
|
73
|
+
end
|
74
|
+
opts.on("--pr-label [LABEL]", "Setup custom label for pull requests section. Default is \"**Merged pull requests:**\"") do |v|
|
75
|
+
options[:merge_prefix] = v
|
76
|
+
end
|
77
|
+
opts.on("--[no-]issues", "Include closed issues in changelog. Default is true") do |v|
|
78
|
+
options[:issues] = v
|
79
|
+
end
|
80
|
+
opts.on("--[no-]issues-wo-labels", "Include closed issues without labels in changelog. Default is true") do |v|
|
81
|
+
options[:add_issues_wo_labels] = v
|
82
|
+
end
|
83
|
+
opts.on("--[no-]pr-wo-labels", "Include pull requests without labels in changelog. Default is true") do |v|
|
84
|
+
options[:add_pr_wo_labels] = v
|
85
|
+
end
|
86
|
+
opts.on("--[no-]pull-requests", "Include pull-requests in changelog. Default is true") do |v|
|
87
|
+
options[:pulls] = v
|
88
|
+
end
|
89
|
+
opts.on("--[no-]filter-by-milestone", "Use milestone to detect when issue was resolved. Default is true") do |last|
|
90
|
+
options[:filter_issues_by_milestone] = last
|
91
|
+
end
|
92
|
+
opts.on("--[no-]author", "Add author of pull-request in the end. Default is true") do |author|
|
93
|
+
options[:author] = author
|
94
|
+
end
|
95
|
+
opts.on("--unreleased-only", "Generate log from unreleased closed issues only.") do |v|
|
96
|
+
options[:unreleased_only] = v
|
97
|
+
end
|
98
|
+
opts.on("--[no-]unreleased", "Add to log unreleased closed issues. Default is true") do |v|
|
99
|
+
options[:unreleased] = v
|
100
|
+
end
|
101
|
+
opts.on("--unreleased-label [label]", "Add to log unreleased closed issues. Default is true") do |v|
|
102
|
+
options[:unreleased_label] = v
|
103
|
+
end
|
104
|
+
opts.on("--[no-]compare-link", "Include compare link (Full Changelog) between older version and newer version. Default is true") do |v|
|
105
|
+
options[:compare_link] = v
|
106
|
+
end
|
107
|
+
opts.on("--include-labels x,y,z", Array, "Only issues with the specified labels will be included in the changelog.") do |list|
|
108
|
+
options[:include_labels] = list
|
109
|
+
end
|
110
|
+
opts.on("--exclude-labels x,y,z", Array, 'Issues with the specified labels will be always excluded from changelog. Default is \'duplicate,question,invalid,wontfix\'') do |list|
|
111
|
+
options[:exclude_labels] = list
|
112
|
+
end
|
113
|
+
opts.on("--bug-labels x,y,z", Array, 'Issues with the specified labels will be always added to "Fixed bugs" section. Default is \'bug,Bug\'') do |list|
|
114
|
+
options[:bug_labels] = list
|
115
|
+
end
|
116
|
+
opts.on("--enhancement-labels x,y,z", Array, 'Issues with the specified labels will be always added to "Implemented enhancements" section. Default is \'enhancement,Enhancement\'') do |list|
|
117
|
+
options[:enhancement_labels] = list
|
118
|
+
end
|
119
|
+
opts.on("--between-tags x,y,z", Array, "Change log will be filled only between specified tags") do |list|
|
120
|
+
options[:between_tags] = list
|
121
|
+
end
|
122
|
+
opts.on("--exclude-tags x,y,z", Array, "Change log will exclude specified tags") do |list|
|
123
|
+
options[:exclude_tags] = list
|
124
|
+
end
|
125
|
+
opts.on("--exclude-tags-regex [REGEX]", "Apply a regular expression on tag names so that they can be excluded, for example: --exclude-tags-regex \".*\+\d{1,}\" ") do |last|
|
126
|
+
options[:exclude_tags_regex] = last
|
127
|
+
end
|
128
|
+
opts.on("--since-tag x", "Change log will start after specified tag") do |v|
|
129
|
+
options[:since_tag] = v
|
130
|
+
end
|
131
|
+
opts.on("--due-tag x", "Change log will end before specified tag") do |v|
|
132
|
+
options[:due_tag] = v
|
133
|
+
end
|
134
|
+
opts.on("--max-issues [NUMBER]", Integer, "Max number of issues to fetch from GitHub. Default is unlimited") do |max|
|
135
|
+
options[:max_issues] = max
|
136
|
+
end
|
137
|
+
opts.on("--release-url [URL]", "The URL to point to for release links, in printf format (with the tag as variable).") do |url|
|
138
|
+
options[:release_url] = url
|
139
|
+
end
|
140
|
+
opts.on("--github-site [URL]", "The Enterprise Github site on which your project is hosted.") do |last|
|
141
|
+
options[:github_site] = last
|
142
|
+
end
|
143
|
+
opts.on("--github-api [URL]", "The enterprise endpoint to use for your Github API.") do |last|
|
144
|
+
options[:github_endpoint] = last
|
145
|
+
end
|
146
|
+
opts.on("--simple-list", "Create simple list from issues and pull requests. Default is false.") do |v|
|
147
|
+
options[:simple_list] = v
|
148
|
+
end
|
149
|
+
opts.on("--future-release [RELEASE-VERSION]", "Put the unreleased changes in the specified release number.") do |future_release|
|
150
|
+
options[:future_release] = future_release
|
151
|
+
end
|
152
|
+
opts.on("--release-branch [RELEASE-BRANCH]", "Limit pull requests to the release branch, such as master or release") do |release_branch|
|
153
|
+
options[:release_branch] = release_branch
|
154
|
+
end
|
155
|
+
opts.on("--[no-]verbose", "Run verbosely. Default is true") do |v|
|
156
|
+
options[:verbose] = v
|
157
|
+
end
|
158
|
+
opts.on("-v", "--version", "Print version number") do |_v|
|
159
|
+
puts "Version: #{GitHubChangelogGenerator::VERSION}"
|
160
|
+
exit
|
161
|
+
end
|
162
|
+
opts.on("-h", "--help", "Displays Help") do
|
163
|
+
puts opts
|
164
|
+
exit
|
165
|
+
end
|
166
|
+
end
|
167
|
+
parser
|
168
|
+
end
|
169
|
+
|
170
|
+
# just get default options
|
171
|
+
def self.default_options
|
172
|
+
{
|
173
|
+
tag1: nil,
|
174
|
+
tag2: nil,
|
175
|
+
date_format: "%Y-%m-%d",
|
176
|
+
output: "CHANGELOG.md",
|
177
|
+
base: "HISTORY.md",
|
178
|
+
issues: true,
|
179
|
+
add_issues_wo_labels: true,
|
180
|
+
add_pr_wo_labels: true,
|
181
|
+
pulls: true,
|
182
|
+
filter_issues_by_milestone: true,
|
183
|
+
author: true,
|
184
|
+
unreleased: true,
|
185
|
+
unreleased_label: "Unreleased",
|
186
|
+
compare_link: true,
|
187
|
+
enhancement_labels: %w(enhancement Enhancement),
|
188
|
+
bug_labels: %w(bug Bug),
|
189
|
+
exclude_labels: %w(duplicate question invalid wontfix Duplicate Question Invalid Wontfix),
|
190
|
+
max_issues: nil,
|
191
|
+
simple_list: false,
|
192
|
+
verbose: true,
|
193
|
+
header: "# Change Log",
|
194
|
+
merge_prefix: "**Merged pull requests:**",
|
195
|
+
issue_prefix: "**Closed issues:**",
|
196
|
+
bug_prefix: "**Fixed bugs:**",
|
197
|
+
enhancement_prefix: "**Implemented enhancements:**",
|
198
|
+
git_remote: "origin"
|
199
|
+
}
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.user_and_project_from_git(options)
|
203
|
+
if options[:user].nil? || options[:project].nil?
|
204
|
+
detect_user_and_project(options, ARGV[0], ARGV[1])
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Detects user and project from git
|
209
|
+
def self.detect_user_and_project(options, arg0 = nil, arg1 = nil)
|
210
|
+
options[:user], options[:project] = user_project_from_option(arg0, arg1, options[:github_site])
|
211
|
+
return if options[:user] && options[:project]
|
212
|
+
|
213
|
+
if ENV["RUBYLIB"] =~ /ruby-debug-ide/
|
214
|
+
options[:user] = "skywinder"
|
215
|
+
options[:project] = "changelog_test"
|
216
|
+
else
|
217
|
+
remote = `git config --get remote.#{options[:git_remote]}.url`
|
218
|
+
options[:user], options[:project] = user_project_from_remote(remote)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Try to find user and project name from git remote output
|
223
|
+
#
|
224
|
+
# @param [String] output of git remote command
|
225
|
+
# @return [Array] user and project
|
226
|
+
def self.user_project_from_option(arg0, arg1, github_site)
|
227
|
+
user = nil
|
228
|
+
project = nil
|
229
|
+
github_site ||= "github.com"
|
230
|
+
if arg0 && !arg1
|
231
|
+
# this match should parse strings such "https://github.com/skywinder/Github-Changelog-Generator" or "skywinder/Github-Changelog-Generator" to user and name
|
232
|
+
puts arg0
|
233
|
+
match = /(?:.+#{Regexp.escape(github_site)}\/)?(.+)\/(.+)/.match(arg0)
|
234
|
+
|
235
|
+
begin
|
236
|
+
param = match[2].nil?
|
237
|
+
rescue
|
238
|
+
puts "Can't detect user and name from first parameter: '#{arg0}' -> exit'"
|
239
|
+
return
|
240
|
+
end
|
241
|
+
if param
|
242
|
+
return
|
243
|
+
else
|
244
|
+
user = match[1]
|
245
|
+
project = match[2]
|
246
|
+
end
|
247
|
+
end
|
248
|
+
[user, project]
|
249
|
+
end
|
250
|
+
|
251
|
+
# Try to find user and project name from git remote output
|
252
|
+
#
|
253
|
+
# @param [String] output of git remote command
|
254
|
+
# @return [Array] user and project
|
255
|
+
def self.user_project_from_remote(remote)
|
256
|
+
# try to find repo in format:
|
257
|
+
# origin git@github.com:skywinder/Github-Changelog-Generator.git (fetch)
|
258
|
+
# git@github.com:skywinder/Github-Changelog-Generator.git
|
259
|
+
regex1 = /.*(?:[:\/])((?:-|\w|\.)*)\/((?:-|\w|\.)*)(?:\.git).*/
|
260
|
+
|
261
|
+
# try to find repo in format:
|
262
|
+
# origin https://github.com/skywinder/ChangelogMerger (fetch)
|
263
|
+
# https://github.com/skywinder/ChangelogMerger
|
264
|
+
regex2 = /.*\/((?:-|\w|\.)*)\/((?:-|\w|\.)*).*/
|
265
|
+
|
266
|
+
remote_structures = [regex1, regex2]
|
267
|
+
|
268
|
+
user = nil
|
269
|
+
project = nil
|
270
|
+
remote_structures.each do |regex|
|
271
|
+
matches = Regexp.new(regex).match(remote)
|
272
|
+
|
273
|
+
if matches && matches[1] && matches[2]
|
274
|
+
puts "Detected user:#{matches[1]}, project:#{matches[2]}"
|
275
|
+
user = matches[1]
|
276
|
+
project = matches[2]
|
277
|
+
end
|
278
|
+
|
279
|
+
break unless matches.nil?
|
280
|
+
end
|
281
|
+
|
282
|
+
[user, project]
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|