learn-tool 0.0.16 → 0.0.20

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d759f8eb4d52c7c0a73d3eb067320d66341085777d1e22cef08c026fc0d02e0
4
- data.tar.gz: 339ede530dbd6f1a4e1aa62a816a91f6bf40b697250582ce549c58cb82dae4d5
3
+ metadata.gz: 71fe36246ba3b898eff013d99569d72091bd0e575ee5efa2d52135e4425bed67
4
+ data.tar.gz: ac8b171728f7ff943d58d6bbe334d406b02e87a6236c781aa96ffac0954c693a
5
5
  SHA512:
6
- metadata.gz: 1c31b985672fa05ea1ed8350103fd00fd536715c2336686ac490aee10cfb33425a9490d4927453182256518f47ea856505825a54309cdb96c128c61bad8cd8df
7
- data.tar.gz: ab74b388effd6db8844f8c6ba89596e4e2fcea0cdafecf468ac98c9952079522d06114d693c8f29fcca7b7573120eadb1cdb214b7f3272c5ad37af9d75eb1c2a
6
+ metadata.gz: 07af1813e35c0678cc0eee5645f79cd68a160b313e537c259e9e090767bf7e6619416df40e91841352d4d64ebc5e7e57d5d4c6960914b7233b07227404b6d7d6
7
+ data.tar.gz: c3b7f30f1e39ec94cad66695614d58de030a8895ccad61d9569a7905a268f71085db9add823aae700dd17d3c7399ff422d0aa553623335e0eb9335f17b5e193e
data/bin/learn-tool CHANGED
@@ -12,9 +12,10 @@ OptionParser.new do |opts|
12
12
  A tool for creating, cloning and repairing repositories. This tool has
13
13
  three basic commands
14
14
 
15
- learn-tool create
16
- learn-tool duplicate
17
- learn-tool repair
15
+ learn-tool --create
16
+ learn-tool --duplicate
17
+ learn-tool --lint <optional: filepath>
18
+ learn-tool --repair <optional: filepath>
18
19
 
19
20
  When creating, you will need to provide a name of the repository you are
20
21
  creating and choose from an existing template.
@@ -25,23 +26,43 @@ OptionParser.new do |opts|
25
26
 
26
27
  EOBANNER
27
28
 
28
- opts.on("--create", "-c", "Create new repository"){ |v| options[:create] = true }
29
- opts.on("--duplicate", "-d", "Clone from existing repository"){ |v| options[:duplicate] = true }
30
- opts.on("--repair", "-r", "Fix current repository"){ |v| options[:repair] = true }
29
+ opts.on("-c", "--create",
30
+ "Create new repository") do |v|
31
+ options[:create] = true
32
+ end
33
+ opts.on("-d", "--duplicate",
34
+ "Clone from existing repository") do |v|
35
+ options[:duplicate] = true
36
+ end
37
+ opts.on("-l", "--lint [ABSOLUTE_FILEPATH]",
38
+ "Lint a directory given its absolute path. If blank, lints current directory") do |filepath|
39
+ filepath ? options[:lint] = filepath : options[:lint] = Dir.pwd
40
+ end
41
+ opts.on("-r", "--repair [ABSOLUTE_FILEPATH]",
42
+ "Add correct files to a directory given its absolute path. If blank, edits current directory") do |filepath|
43
+ filepath ? options[:repair] = filepath : options[:repair] = Dir.pwd
44
+ end
45
+
31
46
  end.parse!
32
47
 
33
48
  puts options
34
49
 
35
50
  if options[:create]
36
- LearnTool.new("create")
51
+ LearnTool.new(mode: "create", filepath: Dir.pwd)
37
52
  end
38
53
 
39
54
  if options[:duplicate]
40
- LearnTool.new("duplicate")
55
+ LearnTool.new(mode: "duplicate", filepath: Dir.pwd)
41
56
  end
42
57
 
43
- if options[:repair]
44
- LearnTool.new("repair")
58
+ if options[:lint]
59
+ LearnTool.new(mode: "lint", filepath: options[:lint])
45
60
  end
46
61
 
62
+ if options[:repair]
63
+ LearnTool.new(mode: "repair", filepath: options[:repair])
64
+ end
47
65
 
66
+ if options == {}
67
+ LearnTool.new(mode: "lint", filepath: Dir.pwd)
68
+ end
data/lib/learn-tool.rb CHANGED
@@ -1,238 +1,50 @@
1
1
  require 'faraday'
2
2
  require 'uri'
3
3
  require 'open3'
4
+ require_relative './learn-tool/learn-base'
5
+ require_relative './learn-tool/learn-repair'
6
+ require_relative './learn-tool/learn-create'
7
+ require_relative './learn-tool/learn-duplicate'
8
+ require_relative './learn-tool/learn-lint'
9
+ require_relative './learn-tool/learn-error'
10
+ require_relative './learn-tool/license-linter'
11
+ require_relative './learn-tool/readme-linter'
12
+ require_relative './learn-tool/yaml-linter'
13
+ require_relative './learn-tool/contributing-linter'
4
14
 
5
15
  class LearnTool
6
- GITHUB_ORG = 'https://api.github.com/repos/learn-co-curriculum/'
7
- README_TEMPLATE = 'readme-template'
8
- RUBY_LAB_TEMPLATE = 'ruby-lab-template'
9
- JAVASCRIPT_LAB_TEMPLATE = 'js-lab-template'
10
- REACT_LAB_TEMPLATE = 'react-lab-template'
16
+
11
17
 
12
- def initialize(mode)
13
- @ssh_configured = check_ssh_config
14
- puts mode
18
+ def initialize(mode:, filepath:Dir.pwd)
19
+ puts filepath
15
20
  if mode == 'create'
16
- create
21
+ LearnCreate.new(filepath)
17
22
  end
18
23
 
19
24
  if mode == 'duplicate'
20
- duplicate
25
+ LearnDuplicate.new(filepath)
21
26
  end
22
27
 
23
28
  if mode == 'repair'
24
- repair
25
- end
26
- end
27
-
28
- def create
29
- puts 'Note: You must have write access to the learn-co-curriculum org on GitHub to use this tool'
30
- until name_new_repo do
31
- puts 'Careful - rate limiting can occur'
29
+ LearnRepair.new(filepath)
32
30
  end
33
31
 
34
- choose_repo_template
35
- create_new_repo
36
- end_message
37
- end
38
-
39
- def choose_repo_template
40
- puts 'Is the lesson you are creating a Readme? (Y/n)'
41
- readme_input = gets.chomp.downcase
42
- if readme_input == "n" || readme_input == "no" || readme_input == "N" || readme_input == "No"
43
- language = choose_language
44
- case language
45
- when /^ru/
46
- @old_repo_name = RUBY_LAB_TEMPLATE
47
- when /^j/
48
- @old_repo_name = JAVASCRIPT_LAB_TEMPLATE
49
- when /^re/
50
- @old_repo_name = REACT_LAB_TEMPLATE
51
- else
52
- @old_repo_name = README_TEMPLATE
53
- end
54
- else
55
- @old_repo_name = README_TEMPLATE
32
+ if mode == 'lint'
33
+ LearnLinter.new(filepath).lint_directory
56
34
  end
57
- @old_repo_name
58
35
  end
59
36
 
60
- def choose_language
61
- language = ''
62
- loop do
63
- puts 'What lab template would you like to use? (Ruby/JavaScript/React)'
64
- language = gets.chomp.downcase
65
- break if language =~ /^(ru|j|re)/
66
- puts 'Please enter Ruby, JavaScript or React, or at minimum, the first two letters:'
67
- puts ''
68
- end
69
- language
70
- end
71
-
72
- def duplicate
73
- puts 'Note: You must have write access to the learn-co-curriculum org on GitHub to use this tool'
74
- loop do
75
- puts 'What is the name of the repository you would like to copy? Paste exactly as is shown in the URL (i.e. advanced-hashes-hashketball)'
76
- old_repo_name_input = gets.strip
77
- if repo_exists(old_repo_name_input)
78
- @old_repo_name = old_repo_name_input
79
- puts ''
80
- puts 'Old repository: ' + @old_repo_name
81
- until name_new_repo do
82
- puts 'Careful - rate limiting can occur'
83
- end
84
-
85
-
86
- create_new_repo
87
- end_message
88
- break
89
- else
90
- puts 'Provided repository name is not a valid learn-co-curriculum repository. Please try again. Careful - rate limiting can be triggered'
91
- end
92
- end
93
- end
37
+
94
38
 
95
- def name_new_repo
96
- puts 'What is the name of the repository you would like to create?'
97
- new_name = gets.strip.gsub(/\s+/, '-').downcase
98
-
99
- if name_length_is_good(new_name)
100
- if !repo_exists(new_name)
101
- @new_repo_name = new_name
102
- else
103
- puts 'A repository with that name already exists. Please try again.'
104
- return false
105
- end
106
- else
107
- puts 'Repository names must be shorter than 100 characters'
108
- return false
109
- end
110
- @new_repo_name
111
- end
112
-
113
- def create_new_repo
114
- # 'cd' doesn't work the way it would in the shell, must be used before every command
115
- puts 'Cloning old repository'
116
- git_clone
117
- # puts "Renaming old directory with new name: #{@new_repo_name}"
118
- # rename_repo
119
- puts ''
120
- puts 'Creating new remote learn-co-curriculum repository'
121
- git_create_and_set_new_origin
122
- puts ''
123
- puts 'Setting new git remote based on SSH settings'
124
- git_set_remote
125
- puts ''
126
- puts 'Pushing all old-remote branches to new remote'
127
- git_push
128
- end
129
-
130
- def end_message
131
- puts ''
132
- puts 'To access local folder, change directory into ' + @new_repo_name + '/'
133
- puts "Repository available at #{GITHUB_ORG}" + @new_repo_name
134
- end
135
-
136
- private
137
-
138
- def git_clone
139
- cmd = "git clone https://github.com/learn-co-curriculum/#{@old_repo_name} #{@new_repo_name}"
140
- puts cmd
141
- `#{cmd}`
142
- end
143
-
144
- def git_create_and_set_new_origin
145
- # Creates repo **and** assigns new remote to 'origin' shortname
146
- cmd = cd_into_and("hub create learn-co-curriculum/#{@new_repo_name}")
147
- puts cmd
148
- `#{cmd}`
149
- end
150
-
151
- def git_set_remote
152
- remote = check_ssh_config ? "git@github.com:learn-co-curriculum/#{@new_repo_name}.git" : "https://github.com/learn-co-curriculum/#{@new_repo_name}"
153
- cmd = cd_into_and("git remote set-url origin #{remote}")
154
- puts cmd
155
- `#{cmd}`
156
- end
157
-
158
- def git_push
159
- # Copy `master`, attempt to copy `solution`, but if it's not there, no complaints
160
- cmds = [
161
- %q|git push origin 'refs/remotes/origin/master:refs/heads/master' > /dev/null 2>&1|,
162
- %q|git push origin 'refs/remotes/origin/solution:refs/heads/solution' > /dev/null 2>&1|
163
- ]
164
- cmds.each { |cmd| `#{cd_into_and(cmd)}` }
165
- end
166
-
167
- def repo_exists(repo_name)
168
- url = GITHUB_ORG + repo_name
169
- encoded_url = URI.encode(url).slice(0, url.length)
170
- check_existing = Faraday.get URI.parse(encoded_url)
171
- !check_existing.body.include? '"Not Found"'
172
- end
173
-
174
- def cd_into_and(command)
175
- "cd #{@new_repo_name} && #{command}"
176
- end
177
-
178
- def create_support_file(name_of_file)
179
- # copies a template folder from the learn_create gem to a subfolder of the current directory
180
- gem_template_location = File.dirname(__FILE__)
181
- template_path = File.expand_path(gem_template_location) + "/support_files/#{name_of_file.upcase}"
182
- cmd = "cp #{template_path} #{Dir.pwd}"
183
- `#{cmd}`
184
- end
185
-
186
- def create_dot_learn_file
187
- `
188
- cat > .learn <<EOL
189
- languages:
190
- - none
191
- `
192
- end
193
39
 
194
- # def create_dot_gitignore_file
195
- # `
196
- # cat > .gitignore <<EOL
197
- # .DS_Store
198
- # logs
199
- # *.log
200
- # npm-debug.log*
201
- # pids
202
- # *.pid
203
- # *.seed
204
- # lib-cov
205
- # build/Release
206
- # node_modules
207
- # jspm_packages
208
- # .npm
209
- # .node_repl_history
210
- # .results.json
211
- # /.bundle
212
- # /db/*.sqlite3
213
- # /db/*.sqlite3-journal
214
- # /log/*
215
- # !/log/.keep
216
- # /tmp
217
- # `
218
- # end
219
40
 
220
41
 
221
42
 
222
- def repair
223
- create_dot_learn_file
224
- create_support_file("LICENSE.md")
225
- create_support_file("CONTRIBUTING.md")
226
- end
43
+
227
44
 
228
- def name_length_is_good(name)
229
- name.length < 100
230
- end
45
+
231
46
 
232
- def check_ssh_config
233
- result = Open3.capture2e('ssh -T git@github.com').first
234
- result.include?("You've successfully authenticated")
235
- end
47
+
236
48
 
237
49
 
238
50
  end
@@ -0,0 +1,23 @@
1
+ class ContributingLinter
2
+
3
+ VALID_FILE = File.open(File.expand_path(File.dirname(__FILE__)) + '/support_files/CONTRIBUTING.md')
4
+
5
+ def self.parse_file(file, learn_error)
6
+ directory_file = sanitize_whitespace(File.open(file).read)
7
+ valid_file_array = sanitize_whitespace(VALID_FILE.read)
8
+ diff = directory_file - valid_file_array
9
+
10
+ if diff.empty?
11
+ learn_error.contributing_error[:valid_contributing] = true
12
+ learn_error.valid_contributing = {message: "valid CONTRIBUTING.md", color: :green}
13
+ else
14
+ learn_error.contributing_error[:valid_contributing] = false
15
+ learn_error.valid_contributing = {message: "invalid CONTRIBUTING.md - Errors: #{diff}", color: :red}
16
+ end
17
+ end
18
+
19
+ def self.sanitize_whitespace(file)
20
+ file.split.delete_if {|char| char.empty? || char == "\n"}
21
+ end
22
+
23
+ end
@@ -0,0 +1,112 @@
1
+ require 'pry'
2
+ class LearnBase
3
+
4
+ GITHUB_ORG = 'https://api.github.com/repos/learn-co-curriculum/'
5
+ README_TEMPLATE = 'readme-template'
6
+ RUBY_LAB_TEMPLATE = 'ruby-lab-template'
7
+ JAVASCRIPT_LAB_TEMPLATE = 'js-lab-template'
8
+ REACT_LAB_TEMPLATE = 'react-lab-template'
9
+
10
+ def initialize(filepath)
11
+ @filepath = filepath
12
+ @old_repo_name = ''
13
+ @new_repo_name = ''
14
+ end
15
+
16
+ def repo_is_available(repo_name)
17
+ url = GITHUB_ORG + repo_name
18
+ encoded_url = URI.encode(url).slice(0, url.length)
19
+ check_existing = Faraday.get URI.parse(encoded_url)
20
+ check_existing.body.include? '"Not Found"'
21
+ end
22
+
23
+ def cd_into_and(filepath, command)
24
+ puts filepath, command
25
+ cmd = "cd #{filepath} && #{command}"
26
+ `#{cmd}`
27
+ end
28
+
29
+ def name_new_repo
30
+ puts 'What is the name of the repository you would like to create?'
31
+ new_name = gets.strip.gsub(/\s+/, '-').downcase
32
+
33
+ if name_length_is_good(new_name)
34
+ if repo_is_available(new_name)
35
+ @new_repo_name = new_name
36
+ else
37
+ puts 'A repository with that name already exists. Please try again.'
38
+ return false
39
+ end
40
+ else
41
+ puts 'Repository names must be shorter than 100 characters'
42
+ return false
43
+ end
44
+ @new_repo_name
45
+ end
46
+
47
+ def get_new_name
48
+ puts 'Note: You must have write access to the learn-co-curriculum org on GitHub to use this tool'
49
+ until name_new_repo do
50
+ puts 'Careful - rate limiting can occur'
51
+ end
52
+ end
53
+
54
+ def create_new_repo
55
+ # 'cd' doesn't work the way it would in the shell, must be used before every command
56
+ puts 'Cloning old repository'
57
+ git_clone
58
+ # puts "Renaming old directory with new name: #{new_repo_name}"
59
+ # rename_repo
60
+ puts ''
61
+ puts 'Creating new remote learn-co-curriculum repository'
62
+ git_create_and_set_new_origin
63
+ puts ''
64
+ puts 'Setting new git remote based on SSH settings'
65
+ git_set_remote
66
+ puts ''
67
+ puts 'Pushing all old-remote branches to new remote'
68
+ git_push
69
+ end
70
+
71
+ def end_message
72
+ puts ''
73
+ puts 'To access local folder, change directory into ' + @new_repo_name + '/'
74
+ puts "Repository available at #{GITHUB_ORG}" + @new_repo_name
75
+ end
76
+
77
+ private
78
+
79
+ def git_clone
80
+ cmd = "git clone https://github.com/learn-co-curriculum/#{@old_repo_name} #{@new_repo_name}"
81
+ puts cmd
82
+ `#{cmd}`
83
+ end
84
+
85
+ def git_create_and_set_new_origin
86
+ # Creates repo **and** assigns new remote to 'origin' shortname
87
+ cd_into_and(@filepath + "/#{@new_repo_name}", "hub create learn-co-curriculum/#{@new_repo_name}")
88
+ end
89
+
90
+ def git_set_remote
91
+ remote = check_ssh_config ? "git@github.com:learn-co-curriculum/#{@new_repo_name}.git" : "https://github.com/learn-co-curriculum/#{new_repo_name}"
92
+ cd_into_and(@filepath + "/#{@new_repo_name}", "git remote set-url origin #{remote}")
93
+ end
94
+
95
+ def git_push
96
+ # Copy `master`, attempt to copy `solution`, but if it's not there, no complaints
97
+ cmds = [
98
+ %q|git push origin 'refs/remotes/origin/master:refs/heads/master' > /dev/null 2>&1|,
99
+ %q|git push origin 'refs/remotes/origin/solution:refs/heads/solution' > /dev/null 2>&1|
100
+ ]
101
+ cmds.each { |cmd| cd_into_and(@filepath + "/#{@new_repo_name}", cmd) }
102
+ end
103
+
104
+ def name_length_is_good(name)
105
+ name.length < 100
106
+ end
107
+
108
+ def check_ssh_config
109
+ result = Open3.capture2e('ssh -T git@github.com').first
110
+ result.include?("You've successfully authenticated")
111
+ end
112
+ end
@@ -0,0 +1,44 @@
1
+ class LearnCreate < LearnBase
2
+
3
+ def initialize(filepath)
4
+ super(filepath)
5
+ get_new_name
6
+ choose_repo_template
7
+ create_new_repo
8
+ end_message
9
+ end
10
+
11
+ def choose_repo_template
12
+ puts 'Is the lesson you are creating a Readme? (Y/n)'
13
+ readme_input = gets.chomp.downcase
14
+ if readme_input == "n" || readme_input == "no" || readme_input == "N" || readme_input == "No"
15
+ language = choose_language
16
+ case language
17
+ when /^ru/
18
+ @old_repo_name = RUBY_LAB_TEMPLATE
19
+ when /^j/
20
+ @old_repo_name = JAVASCRIPT_LAB_TEMPLATE
21
+ when /^re/
22
+ @old_repo_name = REACT_LAB_TEMPLATE
23
+ else
24
+ @old_repo_name = README_TEMPLATE
25
+ end
26
+ else
27
+ @old_repo_name = README_TEMPLATE
28
+ end
29
+ @old_repo_name
30
+ end
31
+
32
+ def choose_language
33
+ language = ''
34
+ loop do
35
+ puts 'What lab template would you like to use? (Ruby/JavaScript/React)'
36
+ language = gets.chomp.downcase
37
+ break if language =~ /^(ru|j|re)/
38
+ puts 'Please enter Ruby, JavaScript or React, or at minimum, the first two letters:'
39
+ puts ''
40
+ end
41
+ language
42
+ end
43
+
44
+ end
@@ -0,0 +1,31 @@
1
+ class LearnDuplicate < LearnBase
2
+
3
+ def initialize(filepath)
4
+ super(filepath)
5
+ puts 'Note: You must have write access to the learn-co-curriculum org on GitHub to use this tool'
6
+ get_old_repo
7
+ end
8
+
9
+ def get_old_repo
10
+ loop do
11
+ puts 'What is the name of the repository you would like to copy? Paste exactly as is shown in the URL (i.e. advanced-hashes-hashketball)'
12
+ old_repo_name_input = gets.strip
13
+ if !repo_is_available(old_repo_name_input)
14
+ @old_repo_name = old_repo_name_input
15
+ puts ''
16
+ puts 'Old repository: ' + @old_repo_name
17
+ until name_new_repo do
18
+ puts 'Careful - rate limiting can occur'
19
+ end
20
+
21
+
22
+ create_new_repo
23
+ end_message
24
+ break
25
+ else
26
+ puts 'Provided repository name is not a valid learn-co-curriculum repository. Please try again. Careful - rate limiting can be triggered'
27
+ end
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,69 @@
1
+ class LearnError < StandardError
2
+ attr_accessor :filepath, :valid_yaml, :valid_license,
3
+ :present_learn, :present_license, :present_readme, :yaml_error,
4
+ :readme_error, :license_error, :valid_readme, :correct_yaml_content,
5
+ :valid_contributing, :present_contributing, :contributing_error
6
+
7
+ ESCAPES = { :green => "\033[32m",
8
+ :yellow => "\033[33m",
9
+ :red => "\033[31m",
10
+ :reset => "\033[0m" }
11
+
12
+
13
+ def initialize
14
+ @yaml_error = {present_dotlearn: false, valid_yaml: false, valid_whitespace: false, attributes: false}
15
+ @readme_error = {present_readme: false, valid_readme: false}
16
+ @license_error = {present_license: false, valid_license: false}
17
+ @contributing_error = {present_contributing: false, valid_contributing: false}
18
+
19
+ @correct_yaml_content = {message: ".learn file must have 'languages' key", color: :red}
20
+
21
+ @valid_yaml = {message: "invalid yaml", color: :red}
22
+ @valid_license = {message: "invalid or missing license content", color: :yellow}
23
+ @valid_readme = {message: [], color: :red}
24
+ @valid_contributing = {message: "invalid or missing contributing content", color: :yellow}
25
+
26
+ @present_learn = {message: "missing .learn file", color: :red}
27
+ @present_license = {message: "missing LICENSE.md", color: :red}
28
+ @present_readme = {message: "missing README.md", color: :red}
29
+ @present_contributing = {message: "missing CONTRIBUTING.md", color: :red}
30
+
31
+ end
32
+
33
+ def emit(opts={})
34
+ color = opts[:color]
35
+ message = opts[:message]
36
+ print ESCAPES[color]
37
+ print message
38
+ print ESCAPES[:reset]
39
+ print "\n"
40
+ end
41
+
42
+ def total_errors
43
+ {
44
+ dot_learn: yaml_error,
45
+ license: license_error,
46
+ readme: readme_error,
47
+ contributing: contributing_error
48
+ }
49
+
50
+ end
51
+
52
+ def result_message
53
+ [present_learn, valid_yaml, correct_yaml_content, present_license, valid_license, present_readme, valid_readme, present_contributing, valid_contributing ]
54
+ end
55
+
56
+
57
+ def result_output
58
+ result_message.each do |result|
59
+ if result[:message].is_a?(Array)
60
+ result[:message].each do |result_message|
61
+ emit({message: result_message, color: result[:color]})
62
+ end
63
+ else
64
+ emit(result)
65
+ end
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,55 @@
1
+ class LearnLinter
2
+ def initialize(filepath)
3
+ @learn_error = LearnError.new
4
+ @filepath = filepath
5
+ end
6
+
7
+ def result_message
8
+ @learn_error.result_message
9
+ end
10
+
11
+ def has_file?(file)
12
+ Dir.entries(@filepath).include?(file) || Dir.entries(@filepath).include?(file.upcase) || Dir.entries(@filepath).include?(file.downcase)
13
+ end
14
+
15
+ def lint_directory
16
+ self.yaml_lint
17
+ self.license_lint
18
+ self.readme_lint
19
+ self.contributing_lint
20
+ @learn_error.result_output
21
+ @learn_error.total_errors
22
+ end
23
+
24
+ def yaml_lint
25
+ if self.has_file?(".learn")
26
+ @learn_error.yaml_error[:present_dotlearn] = true
27
+ @learn_error.present_learn = {message: "present .learn file", color: :green}
28
+ YamlLint.parse_file("#{@filepath}/.learn", @learn_error)
29
+ end
30
+ end
31
+
32
+ def license_lint
33
+ if self.has_file?("LICENSE.md")
34
+ @learn_error.license_error[:present_license] = true
35
+ @learn_error.present_license = {message: "present LICENSE.md", color: :green}
36
+ LicenseLinter.parse_file("#{@filepath}/LICENSE.md", @learn_error)
37
+ end
38
+ end
39
+
40
+ def readme_lint
41
+ if self.has_file?("README.md")
42
+ @learn_error.readme_error[:present_readme] = true
43
+ @learn_error.present_readme = {message: "present README.md", color: :green}
44
+ ReadmeLinter.parse_file("#{@filepath}/README.md", @learn_error)
45
+ end
46
+ end
47
+
48
+ def contributing_lint
49
+ if self.has_file?("CONTRIBUTING.md")
50
+ @learn_error.contributing_error[:present_contributing] = true
51
+ @learn_error.present_contributing = {message: "present CONTRIBUTING.md", color: :green}
52
+ ContributingLinter.parse_file("#{@filepath}/CONTRIBUTING.md", @learn_error)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,25 @@
1
+ class LearnRepair < LearnBase
2
+
3
+ def initialize(filepath)
4
+ super(filepath)
5
+ cd_into_and(filepath, create_dot_learn_file)
6
+ cd_into_and(filepath, create_support_file("LICENSE.md"))
7
+ cd_into_and(filepath, create_support_file("CONTRIBUTING.md"))
8
+ end
9
+
10
+ def create_dot_learn_file
11
+ `
12
+ cat > .learn <<- EOL
13
+ languages:
14
+ - none
15
+ `
16
+ end
17
+
18
+ def create_support_file(name_of_file)
19
+ # copies a template folder from the learn_create gem to a subfolder of the current directory
20
+ gem_template_location = File.dirname(__FILE__)
21
+ template_path = File.expand_path(gem_template_location) + "/support_files/#{name_of_file}"
22
+ "cp #{template_path} #{@filepath}"
23
+ end
24
+
25
+ end
@@ -0,0 +1,27 @@
1
+ class LicenseLinter
2
+
3
+ VALID_FILE = File.open(File.expand_path(File.dirname(__FILE__)) + '/support_files/LICENSE.md')
4
+ VALID_YEARS = ["2015","2016","2017","2018","2019","2020","2021","2022","2023","2024","2025"]
5
+
6
+ def self.parse_file(file, learn_error)
7
+ directory_file_array = sanitize_whitespace(File.open(file).read)
8
+ valid_file_array = sanitize_whitespace(VALID_FILE.read)
9
+ diff = directory_file_array - valid_file_array
10
+
11
+ VALID_YEARS.each do |year|
12
+ diff.delete(year)
13
+ end
14
+
15
+ if diff.empty?
16
+ learn_error.license_error[:valid_license] = true
17
+ learn_error.valid_license = {message: "valid LICENSE.md", color: :green}
18
+ else
19
+ learn_error.license_error[:valid_license] = false
20
+ learn_error.valid_license = {message: "invalid LICENSE.md - Errors: #{diff}", color: :red}
21
+ end
22
+ end
23
+
24
+ def self.sanitize_whitespace(file)
25
+ file.split.delete_if {|char| char.empty? || char == "\n"}
26
+ end
27
+ end
@@ -0,0 +1,55 @@
1
+ class ReadmeLinter
2
+
3
+ def self.parse_file(file, learn_error)
4
+ if has_code_snippets?(file)
5
+ lines = collect_lines(file)
6
+ validate_snippets(lines, learn_error)
7
+ else
8
+ green_light(learn_error)
9
+ end
10
+ end
11
+
12
+ def self.green_light(learn_error)
13
+ learn_error.readme_error[:valid_readme] = true
14
+ learn_error.valid_readme = {message: "valid readme", color: :green}
15
+ end
16
+
17
+ def self.has_code_snippets?(file)
18
+ file_content = File.open(file).read
19
+ file_content.match(/``/)
20
+ end
21
+
22
+ def self.collect_lines(file)
23
+ lines = {}
24
+ File.foreach(file) do |line_content|
25
+ lines["#{$.}"] = line_content
26
+ end
27
+ lines
28
+ end
29
+
30
+ def self.validate_snippets(lines, learn_error)
31
+ lint_lines(lines, learn_error)
32
+ total_errors?(learn_error)
33
+ end
34
+
35
+ def self.lint_lines(lines, learn_error)
36
+ lines.each do |line_num, line_content|
37
+ if line_content.match(/``/)
38
+ if !(line_content.match(/^```(ruby|rb|bash|sh|swift|html|erb|js|javascript|objc|java|sql|css|text|python)?$/))
39
+ learn_error.valid_readme[:message] << "INVALID CODE SNIPPET - line #{line_num}: #{line_content}"
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ def self.total_errors?(learn_error)
46
+ if error_free?(learn_error)
47
+ green_light(learn_error)
48
+ end
49
+ end
50
+
51
+ def self.error_free?(learn_error)
52
+ learn_error.valid_readme[:message].empty?
53
+ end
54
+ end
55
+
@@ -0,0 +1,44 @@
1
+ require 'yaml'
2
+
3
+ class YamlLint
4
+
5
+
6
+ def self.parse_file(file, learn_error)
7
+ begin
8
+ YAML.load_file(file)
9
+ rescue Exception => err
10
+ learn_error.valid_yaml = {message: "#{err}", color: :red}
11
+ else
12
+ learn_error.yaml_error[:valid_yaml] = true
13
+ if check_attributes(file)
14
+ learn_error.yaml_error[:attributes] = true
15
+ learn_error.correct_yaml_content = {message: "valid attribute key names", color: :green}
16
+ end
17
+ if self.validate_whitespace_for_learn(file)
18
+ learn_error.yaml_error[:valid_whitespace] = true
19
+ learn_error.valid_yaml = {message: "valid yaml and valid whitespace.", color: :green}
20
+ else
21
+ learn_error.valid_yaml = {message: "valid yaml but invalid whitespace", color: :red}
22
+ end
23
+ end
24
+ end
25
+
26
+ def self.validate_whitespace_for_learn(file)
27
+ lines = file_lines(file).split("\n")
28
+ attributes = lines.select { |line| line.include?("-") }
29
+ attributes.each do |attribute|
30
+ return false unless attribute[0..3] == " - "
31
+ end
32
+ true
33
+ end
34
+
35
+ def self.check_attributes(file)
36
+ file_string = file_lines(file)
37
+ file_string.match(/languages/)
38
+ end
39
+
40
+ def self.file_lines(file)
41
+ f = File.read(file)
42
+ end
43
+
44
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: learn-tool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - flatironschool
@@ -38,8 +38,18 @@ files:
38
38
  - Rakefile
39
39
  - bin/learn-tool
40
40
  - lib/learn-tool.rb
41
- - lib/support_files/CONTRIBUTING.md
42
- - lib/support_files/LICENSE.md
41
+ - lib/learn-tool/contributing-linter.rb
42
+ - lib/learn-tool/learn-base.rb
43
+ - lib/learn-tool/learn-create.rb
44
+ - lib/learn-tool/learn-duplicate.rb
45
+ - lib/learn-tool/learn-error.rb
46
+ - lib/learn-tool/learn-lint.rb
47
+ - lib/learn-tool/learn-repair.rb
48
+ - lib/learn-tool/license-linter.rb
49
+ - lib/learn-tool/readme-linter.rb
50
+ - lib/learn-tool/support_files/CONTRIBUTING.md
51
+ - lib/learn-tool/support_files/LICENSE.md
52
+ - lib/learn-tool/yaml-linter.rb
43
53
  homepage: https://github.com/learn-co-curriculum/learn-tool
44
54
  licenses:
45
55
  - MIT