richcss 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 09d0e0a3a4e317c7dafce1aa4d3c1fc5cd2b6e1f
4
+ data.tar.gz: 411df6d822124af8ec79443d4afc5c48131518fe
5
+ SHA512:
6
+ metadata.gz: 2877d5bea707c176149564ba298572015a8c13e0bb754bdceaaf475f2ce524fe537b0ea00181cce8aae4455f2a49e888038d126ba3d82a0837fcf87e46ce991a
7
+ data.tar.gz: ff506b25f7dcec0ad306896a2462c2b489081b1353415dbdf6f8b47f56beecfaed9d31ae2de5c367ab194f8d1592237b21379bf0114ef0f8f5e6c829df01fed3
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /*.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in richcss.gemspec
4
+ gemspec
5
+
6
+ gem 'version_kit', git: 'https://github.com/CocoaPods/VersionKit.git', branch: 'master'
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 TODO: Write your name
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Richcss-cli
2
+
3
+ Richcss CLI is a tool to manage your CSS using the RichCSS framework.
4
+ It also includes a package manager to help install and create your own RichCSS parts for others to use.
5
+
6
+ Both CSS and SASS are supported.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'richcss'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install richcss
23
+
24
+
25
+ ## Usage
26
+
27
+ ### Using RichCSS in your project
28
+
29
+ To start, in the directory where you want to put all your CSS, run
30
+
31
+ $ richcss init
32
+
33
+ to create the skeleton structure. Currently, only CSS is supported by `init`.
34
+
35
+ #### Using RichCSS parts
36
+
37
+ In the directory created using `richcss init`, you can install third-party parts using
38
+
39
+ $ richcss install <PART> [VERSION]
40
+
41
+ The version is optional and will default to the latest version of that part.
42
+
43
+ ### Creating your own RichCSS Part
44
+
45
+ Generate the necessary files for your Part with
46
+
47
+ $ richcss part init <PART_NAME>
48
+
49
+ #### Publishing your Part for others to use
50
+
51
+ Before releasing your Part to the public, you may run
52
+
53
+ $ richcss part check [PART_PATH]
54
+
55
+ to make sure everything is valid. Then publish it to CSSParts with
56
+
57
+ $ richcss part push <PART_NAME>
58
+
59
+
60
+ ## Development
61
+
62
+ After checking out the repo, run `bundle install` to install dependencies.
63
+ To install this gem onto your local machine, run `bundle exec rake install`.
64
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
65
+ which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
66
+
67
+
68
+ ## Contributing
69
+
70
+ Bug reports and pull requests are welcome on GitHub at https://github.com/fdp-A4/richcss-cli
71
+
72
+
73
+ ## License
74
+
75
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
76
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "richcss"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/richcss ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'richcss'
3
+ require 'richcss/cli'
4
+
5
+ RichcssCLI::Cli.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/exe/richcss ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ require 'richcss'
3
+ require 'richcss/cli'
4
+
5
+ RichcssCLI::Cli.start
@@ -0,0 +1,105 @@
1
+ require 'thor'
2
+ require 'richcss'
3
+
4
+ module RichcssCLI
5
+ class Part < Thor
6
+ desc "init <PART_NAME>", "Generate a skeleton directory for your new Rich CSS part"
7
+ # part_name
8
+ # |--- lib
9
+ # | |--- elements
10
+ # | | |--- ...
11
+ # | |--- box
12
+ # | | |--- ...
13
+ # |--- part_name.spec
14
+ # |--- README.md
15
+ def init(part)
16
+ Richcss::Generators::PartTemplate.start([part])
17
+ end
18
+
19
+ desc "check [PART_PATH]", "Validate folder/file structure of the Rich CSS part, optionally passing in a path"
20
+ def check(part_dir_name=nil)
21
+ part_path = "#{Dir.pwd}" + "/" + "#{part_dir_name}" || Dir.pwd
22
+ result = Richcss::Manager.check(part_path)
23
+ Dir.chdir(part_path)
24
+ if !result.nil?
25
+ puts result
26
+ return false
27
+ end
28
+
29
+ partPathSplit = part_path.split("/")
30
+ partName = partPathSplit[partPathSplit.length - 1]
31
+
32
+ puts "Passed all validation checks, part: #{partName} is ready for upload!"
33
+ return true
34
+ end
35
+
36
+ desc "push <PART_PATH>", "Attempt to upload a new Rich CSS part to our servers"
37
+ def push(part_dir_name=nil)
38
+ part_path = "#{Dir.pwd}" + "/" + "#{part_dir_name}" || Dir.pwd
39
+ if check(part_dir_name)
40
+ Richcss::Manager.upload(part_path)
41
+ end
42
+ end
43
+ end
44
+
45
+ class Cli < Thor
46
+ desc "init", "Initialize current directory to follow the Rich CSS framework"
47
+ # elements
48
+ # |--- ...
49
+ # box
50
+ # |--- ...
51
+ # parts
52
+ # |--- ...
53
+ def init()
54
+ Richcss::Generators::Template.start()
55
+ end
56
+
57
+ desc "install <PART> [VERSION]", "Install the part requested into the Parts directory"
58
+ def install(part_name, part_version='')
59
+ installed_parts = Richcss::Part.get_or_create_partfile()
60
+ if part_version.eql?('')
61
+ RestClient.get("http://www.cssparts.com/api/part/#{part_name}") { |response, request, result, &block|
62
+ if response.code == 200
63
+ body = JSON.parse(response.to_str)
64
+ part_version = body["version"]
65
+ elsif response.code == 400
66
+ puts "Part: #{part_name} cannot be found."
67
+ return
68
+ else
69
+ puts "Error #{response.code} retrieving Part: #{part_name}"
70
+ return
71
+ end
72
+ }
73
+ else
74
+ RestClient.get("http://www.cssparts.com/api/part/#{part_name}", {:params => {'version' => part_version}}) { |response, request, result, &block|
75
+ if response.code == 400
76
+ puts "Part: #{part_name} #{part_version} does not exist."
77
+ return
78
+ elsif response.code != 200
79
+ puts "Error #{response.code} retrieving Part: #{part_name} #{part_version}"
80
+ return
81
+ end
82
+ }
83
+ end
84
+
85
+ if installed_parts.key?(part_name) and installed_parts[part_name].eql?(part_version)
86
+ puts "Part #{part_name} v#{part_version} is already installed!"
87
+ return
88
+ end
89
+
90
+ partfileList = ''
91
+ dep_list = Richcss::Part.resolve_dependencies(part_name, part_version, installed_parts)
92
+ dep_list.each do |dep|
93
+ Richcss::Part.fetch(dep.name, dep.version)
94
+ partfileList << dep.name << " " << dep.version.to_s << "\n"
95
+ end
96
+
97
+ File.open('parts/Partfile', 'wb') do |f|
98
+ f.write(partfileList)
99
+ end
100
+ end
101
+
102
+ desc "part", "Commands for creating and uploading your own Rich CSS parts"
103
+ subcommand "part", Part
104
+ end
105
+ end
@@ -0,0 +1,18 @@
1
+ /* Import all your CSS files here */
2
+
3
+ /* Box CSS */
4
+ @import 'box/blocks.scss';
5
+ @import 'box/main.scss';
6
+ @import 'box/positioning.scss';
7
+
8
+ /* Element CSS */
9
+ @import 'elements/buttons.scss';
10
+ @import 'elements/colors.scss';
11
+ @import 'elements/features.scss';
12
+ @import 'elements/fonts.scss';
13
+ @import 'elements/images.scss';
14
+ @import 'elements/inputs.scss';
15
+ @import 'elements/lists.scss';
16
+
17
+ /* Parts CSS */
18
+ @import 'parts/parts.scss';
@@ -0,0 +1,109 @@
1
+ require 'thor/group'
2
+ require 'json'
3
+
4
+ module Richcss
5
+ module Generators
6
+ class Template < Thor::Group
7
+ include Thor::Actions
8
+
9
+ def self.source_root
10
+ File.dirname(__FILE__) + "/generator"
11
+ end
12
+
13
+ def init
14
+ @groups = ['box', 'elements', 'parts']
15
+ @boxFiles = ['blocks', 'main', 'positioning']
16
+ @elementFiles = ['button', 'colors', 'features', 'fonts', 'images', 'inputs', 'lists']
17
+ @partFiles = ['Partfile']
18
+ end
19
+
20
+ def create_folders
21
+ @groups.each do |g|
22
+ empty_directory("#{g}") unless Dir.exists?("#{g}")
23
+ end
24
+ end
25
+
26
+ def create_css_files
27
+ # TODO: add choice of CSS or SCSS files to generate
28
+ # TODO: Make it not hardcode box/elements
29
+ extension = ".css"
30
+ # extension = ".css.scss"
31
+ @boxFiles.each do |filename|
32
+ create_file "box/#{filename}#{extension}" unless File.file?("box/#{filename}#{extension}")
33
+ end
34
+
35
+ @elementFiles.each do |filename|
36
+ create_file "elements/#{filename}#{extension}" unless File.file?("elements/#{filename}#{extension}")
37
+ end
38
+ end
39
+
40
+ def create_partfile
41
+ create_file "parts/Partfile" unless File.file?("parts/Partfile")
42
+ end
43
+ end
44
+
45
+ class PartTemplate < Thor::Group
46
+ include Thor::Actions
47
+
48
+ argument :part_name, :type => :array
49
+ # argument :part, :type => :array
50
+ # argument :part_name, :type => :string
51
+
52
+ def self.source_root
53
+ File.dirname(__FILE__) + "/generator"
54
+ end
55
+
56
+ def init
57
+ @name = part_name.first
58
+ @groups = ['box', 'elements']
59
+ @boxFiles = ['blocks', 'main', 'positioning']
60
+ @elementFiles = ['button', 'colors', 'features', 'fonts', 'images', 'inputs', 'lists']
61
+ end
62
+
63
+ def create_folders
64
+ empty_directory(@name) unless Dir.exists?(@name)
65
+ empty_directory("#{@name}/lib") unless Dir.exists?("#{@name}/lib")
66
+ @groups.each do |g|
67
+ empty_directory("#{@name}/lib/#{g}") unless Dir.exists?("#{@name}/lib/#{g}")
68
+ end
69
+ end
70
+
71
+ def create_css_files
72
+ # TODO: add choice of CSS or SCSS files to generate
73
+ # TODO: Make it not hardcode box/elements
74
+ extension = ".css"
75
+ # extension = ".css.scss"
76
+ @boxFiles.each do |filename|
77
+ create_file "#{@name}/lib/box/#{filename}#{extension}" unless File.file?("#{@name}/lib/box/#{filename}#{extension}")
78
+ end
79
+
80
+ @elementFiles.each do |filename|
81
+ create_file "#{@name}/lib/elements/#{filename}#{extension}" unless File.file?("#{@name}/lib/elements/#{filename}#{extension}")
82
+ end
83
+ end
84
+
85
+ def create_files
86
+ create_file "#{@name}/README.md" unless File.file?("#{@name}/README.md")
87
+
88
+ if !File.file?("#{@name}/#{@name.downcase}.spec")
89
+ create_file "#{@name}/#{@name.downcase}.spec"
90
+ # Write JSON to Test.Spec
91
+ specs = {
92
+ "name" => "#{@name}",
93
+ "authors" => "AUTHOR_NAME",
94
+ "email" => "AUTHOR_EMAIL",
95
+ "description" => "DESCRIPTION",
96
+ "version" => "0.0.0",
97
+ "homepage" => "GITHUB_REPO_URL",
98
+ "dependencies" => {
99
+ "DEPENDECY_NAME" => "DEPENDECY_VERSION"
100
+ }
101
+ }
102
+ File.open("#{@name}/#{@name.downcase}.spec","w") do |f|
103
+ f.write(JSON.pretty_generate(specs))
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,213 @@
1
+ require 'richcss'
2
+ require 'rest-client'
3
+ require 'json'
4
+ require 'active_model'
5
+ require 'email_validator'
6
+
7
+ module Richcss
8
+ class Manager
9
+ # Checks if the folder has the required format for uploading
10
+ def self.check(check_dir)
11
+ Dir.chdir(check_dir)
12
+
13
+ # LEVEL 1
14
+ # Find the spec file and the part name
15
+ part_name = ''
16
+ specFilePath = ''
17
+ Dir.glob("*.spec").each do |f|
18
+ part_name = File.basename(f, '.spec')
19
+ specFilePath = "#{check_dir}/#{f}"
20
+ end
21
+ if part_name.empty?
22
+ return "Rich CSS spec file not found"
23
+ end
24
+
25
+ # Check if readme exists
26
+ if !File.file?("#{check_dir}/README.md")
27
+ return "README.md file not found"
28
+ end
29
+
30
+ if !Dir.exist?('lib')
31
+ return "lib folder not found"
32
+ end
33
+
34
+ # LEVEL 2 / LIB
35
+ Dir.chdir('lib')
36
+ groups = ['box', 'elements']
37
+
38
+ groups.each do |g|
39
+ if !Dir.exist?(g)
40
+ return "#{g} folder not found in lib"
41
+ end
42
+ end
43
+
44
+ # LEVEL 3 BOX/ELEMENTS/PARTS
45
+ # TODO: Don't do this hardcoded for box/elements, use like some hashmap or something..
46
+ boxFiles = ['blocks', 'main', 'positioning']
47
+ elementFiles = ['button', 'colors', 'features', 'fonts', 'images', 'inputs', 'lists']
48
+ validExtensions = ['.css', '.css.scss']
49
+
50
+ fileCount = 0
51
+ Dir.foreach('box') do |filename|
52
+ next if filename == '.' or filename == '..'
53
+ boxFiles.each do |b|
54
+ validExtensions.each do |ext|
55
+ if filename == "#{b}#{ext}"
56
+ fileCount += 1
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ if fileCount < boxFiles.size
63
+ return "Missing css files in box folder, required #{boxFiles}"
64
+ end
65
+
66
+ fileCount = 0
67
+ Dir.foreach('elements') do |filename|
68
+ next if filename == '.' or filename == '..'
69
+ elementFiles.each do |b|
70
+ validExtensions.each do |ext|
71
+ if filename == "#{b}#{ext}"
72
+ fileCount += 1
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ if fileCount < elementFiles.size
79
+ return "Missing css files in elements folder, required #{elementFiles}"
80
+ end
81
+
82
+ # SPEC FILE CHECK
83
+ specFile = "#{part_name}.spec"
84
+
85
+ begin
86
+ jsonData = File.read(specFilePath)
87
+ hash = JSON.parse(jsonData)
88
+ rescue
89
+ return "Invalid Json format in #{specFile}"
90
+ end
91
+
92
+ defaultSpecs = {
93
+ "authors" => "AUTHOR_NAME",
94
+ "email" => "AUTHOR_EMAIL",
95
+ "description" => "DESCRIPTION",
96
+ "homepage" => "GITHUB_REPO_URL"
97
+ }
98
+ requiredSpecs = ['name', 'authors', 'email', 'description', 'version', 'homepage', 'dependencies']
99
+
100
+ # Ensure each spec exist
101
+ requiredSpecs.each do |spec|
102
+ if hash[spec].nil? && spec != 'dependencies'
103
+ return "Missing \"#{spec}\" definition in #{specFile}"
104
+ end
105
+ end
106
+
107
+ # Check for default entries
108
+ defaultSpecs.keys.each do |spec|
109
+ if hash[spec] == defaultSpecs[spec]
110
+ return "Default value for \"#{spec}\" in #{specFile} is being used, please change it to a valid entry"
111
+ end
112
+ end
113
+
114
+ # Check email
115
+ if !EmailValidator.valid?(hash[requiredSpecs[2]])
116
+ return "Email address is invalid"
117
+ end
118
+
119
+ # Check Part_Name
120
+ if (hash[requiredSpecs[0]] != part_name)
121
+ return "Invalid part name: \"#{hash[requiredSpecs[0]]}\" in #{specFile}, should be \"#{part_name}\""
122
+ end
123
+
124
+
125
+ # Check if github url exist
126
+ uri = URI.parse(hash[requiredSpecs[5]])
127
+
128
+ http_object = Net::HTTP.new(uri.host, uri.port)
129
+ http_object.use_ssl = true if uri.scheme == 'https'
130
+ begin
131
+ http_object.start do |http|
132
+ request = Net::HTTP::Get.new uri.request_uri
133
+ http.read_timeout = 500
134
+ http.request request do |response|
135
+ case response
136
+ when Net::HTTPNotFound then
137
+ return "Could not access GitHub url, please use a public repository"
138
+ end
139
+ end
140
+ end
141
+ rescue
142
+ return "Invalid URL for homepage"
143
+ end
144
+
145
+ # Check for version
146
+ begin
147
+ resp = RestClient.get "http://www.cssparts.com/api/part/#{part_name}"
148
+ if resp.code == 200
149
+ body = JSON.parse(resp.to_str)
150
+ current_version = body["version"]
151
+ part_version = hash[requiredSpecs[4]]
152
+ if Gem::Version.new(current_version) >= Gem::Version.new(part_version)
153
+ return "Part version: \"#{part_version}\" in #{specFile} must be greater than existing version: \"#{current_version}\""
154
+ end
155
+ end
156
+ rescue RestClient::ExceptionWithResponse => e
157
+ end
158
+
159
+ # Check dependency existance
160
+ dependencies = hash[requiredSpecs[6]]
161
+ if dependencies.nil? || dependencies.empty?
162
+ return nil
163
+ end
164
+
165
+ begin
166
+ dependencies = dependencies.to_a.map { |x| "#{x[0]}=#{x[1].to_s}" }.join("&")
167
+ resp = RestClient.get "http://www.cssparts.com/api/validateDependencies/#{dependencies}"
168
+ rescue RestClient::ExceptionWithResponse => e
169
+ return e.response
170
+ end
171
+
172
+ return nil
173
+ end
174
+
175
+ # Fetch url and download the part
176
+ def self.getPartData(part_name)
177
+ begin
178
+ resp = RestClient.get "http://www.cssparts.com/api/part/#{part_name}"
179
+ if resp.code == 200
180
+ body = JSON.parse(resp.to_str)
181
+ return body
182
+ else
183
+ puts "Error: Part #{name} cannot be found."
184
+ end
185
+ rescue RestClient::ExceptionWithResponse => e
186
+ puts e.response
187
+ end
188
+ return nil
189
+ end
190
+
191
+ def self.upload(part_path)
192
+ partPathSplit = part_path.split("/")
193
+ partName = partPathSplit[partPathSplit.length - 1]
194
+
195
+ if !File.file?("#{part_path}/#{partName}.spec")
196
+ puts "#{part_path}/#{partName}.spec file not found"
197
+ return
198
+ end
199
+
200
+ specs = File.read("#{part_path}/#{partName}.spec")
201
+ specsJson = JSON.parse(specs)
202
+
203
+ begin
204
+ puts RestClient.post "http://www.cssparts.com/api/upload", :name => partName, :description => specsJson["description"],
205
+ :version => specsJson["version"], :authors => specsJson["authors"], :email => specsJson["email"], :homepage => specsJson["homepage"],
206
+ :dependencies => specsJson["dependencies"]
207
+ rescue RestClient::ExceptionWithResponse => e
208
+ puts e.response
209
+ end
210
+ end
211
+
212
+ end
213
+ end
@@ -0,0 +1,119 @@
1
+ require 'json'
2
+ require 'rest-client'
3
+ require 'uri'
4
+ require 'zipruby'
5
+
6
+ module Richcss
7
+ class Part
8
+ attr_accessor :name
9
+
10
+ # placeholder for latest version is blank
11
+ def self.resolve_dependencies(part_name, version, installed={})
12
+ dep_list = Richcss::Resolver.start(part_name, version, installed)
13
+ end
14
+
15
+ def self.get_or_create_partfile()
16
+ if !Dir.exists?('parts')
17
+ FileUtils.mkdir_p('parts')
18
+ end
19
+
20
+ parts = Hash.new
21
+ Dir.chdir('parts') do
22
+ part_file = "Partfile"
23
+
24
+ begin
25
+ File.open(part_file, "r") do |f|
26
+ f.each_line do |line|
27
+ part, version = line.split(" ")
28
+ parts[part] = version
29
+ end
30
+ end
31
+ rescue
32
+ File.new(part_file, "w")
33
+ end
34
+ end
35
+
36
+ return parts
37
+ end
38
+
39
+ # Fetch url and download the part
40
+ def self.fetch(part_name, version)
41
+ puts "Fetching part #{part_name}"
42
+
43
+ begin
44
+ resp = RestClient.get "http://www.cssparts.com/api/part/#{part_name}"
45
+ if resp.code == 200
46
+ body = JSON.parse(resp.to_str)
47
+ homepage = body["homepage"]
48
+ homepage.slice! "https:\/\/github.com\/"
49
+ homepage = homepage.split("\/")
50
+ repo_owner = homepage[0]
51
+ repo_name = homepage[1]
52
+ jsonResponse = JSON.parse(Net::HTTP.get(URI("https://api.github.com/repos/#{repo_owner}/#{repo_name}/releases/tags/v#{body["version"]}")))
53
+ downloadLink = jsonResponse["zipball_url"]
54
+ install(part_name, body["version"], downloadLink)
55
+ else
56
+ puts "Error: Part #{name} cannot be found."
57
+ end
58
+ rescue RestClient::ExceptionWithResponse => e
59
+ puts e.response
60
+ end
61
+ end
62
+
63
+ # Install this part
64
+ def self.install(part_name, version, resource)
65
+ uri = URI.parse(resource)
66
+
67
+ http_object = Net::HTTP.new(uri.host, uri.port)
68
+ http_object.use_ssl = true if uri.scheme == 'https'
69
+ begin
70
+ http_object.start do |http|
71
+ request = Net::HTTP::Get.new uri.request_uri
72
+ http.read_timeout = 500
73
+ http.request request do |response|
74
+ case response
75
+ when Net::HTTPRedirection then
76
+ location = response['location']
77
+ install(part_name, version, location)
78
+ else
79
+ puts "Installing part..."
80
+
81
+ if !Dir.exists?('parts')
82
+ FileUtils.mkdir_p('parts')
83
+ end
84
+
85
+ Dir.chdir('parts') do
86
+ if Dir.exists?(part_name)
87
+ FileUtils.remove_dir(part_name)
88
+ end
89
+ Zip::Archive.open_buffer(response.body) do |ar|
90
+ #save the directory name for rename later
91
+ oldDirName = ar.get_name(0)
92
+
93
+ ar.each do |zf|
94
+ if zf.directory?
95
+ FileUtils.mkdir_p(zf.name)
96
+ else
97
+ dirname = File.dirname(zf.name)
98
+ FileUtils.mkdir_p(dirname) unless File.exist?(dirname)
99
+ open(zf.name, 'wb') do |f|
100
+ f << zf.read
101
+ end
102
+ end
103
+ end
104
+
105
+ FileUtils.mv oldDirName, part_name
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ RestClient.post "http://www.cssparts.com/api/part/downloaded", :name => part_name, :version => version
113
+ rescue Exception => e
114
+ puts e
115
+ end
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,27 @@
1
+ require 'molinillo'
2
+ require 'version_kit'
3
+
4
+ module Richcss
5
+ class Resolver
6
+
7
+ def self.start(part_name, version, installed = {})
8
+ requirements = [VersionKit::Dependency.new(part_name, version)]
9
+ installed.each do | p, v |
10
+ requirements.push(VersionKit::Dependency.new(p, v))
11
+ end
12
+ @resolver = Molinillo::Resolver.new(RichSpecificationProvider.new(part_name, version), RichUI.new)
13
+ @base_dg = Molinillo::DependencyGraph.new
14
+ dg = @resolver.resolve(requirements, @base_dg)
15
+ puts "Succesfully resolved dependencies:\n"
16
+ dg.map(&:payload).flatten
17
+ rescue Molinillo::VersionConflict => e
18
+ puts e
19
+ rescue Molinillo::CircularDependencyError => e
20
+ names = e.dependencies.sort_by(&:name).map {|d| "gem '#{d.name}'" }
21
+ puts "Your RichCSS part requires parts that depend" \
22
+ " on each other, creating an circular loop. Please remove" \
23
+ " #{names.count > 1 ? "either " : ""}#{names.join(" or ")}" \
24
+ " and try again."
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,75 @@
1
+ require 'version_kit'
2
+ require 'molinillo'
3
+
4
+ module Richcss
5
+ class RichSpecificationProvider
6
+ attr_accessor :specs
7
+ attr_accessor :part_name
8
+ attr_accessor :version
9
+
10
+ include Molinillo::SpecificationProvider
11
+
12
+ def initialize(name, version)
13
+ self.part_name = name
14
+ self.version = version
15
+ response = RestClient.get "http://www.cssparts.com/api/part/#{name}/dependency", {:params => {'version' => version}}
16
+ if response.code == 200
17
+ self.specs = JSON.load(response.body).reduce(Hash.new([])) do |specs_by_name, (dep_name, dep_versions)|
18
+ specs_by_name.tap do |specs|
19
+ specs[dep_name] = dep_versions.map { |s| Richcss::TestSpecification.new s }.sort_by(&:version)
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ def requirement_satisfied_by?(requirement, _activated, spec)
26
+ requirement.satisfied_by?(spec.version)
27
+ end
28
+
29
+ def search_for(dependency)
30
+ @search_for ||= {}
31
+ @search_for[dependency] ||= begin
32
+ pre_release = dependency_pre_release?(dependency)
33
+ specs[dependency.name].select do |spec|
34
+ (pre_release ? true : !spec.version.pre_release?) &&
35
+ dependency.satisfied_by?(spec.version)
36
+ end
37
+ end
38
+ end
39
+
40
+ def name_for(dependency)
41
+ dependency.name
42
+ end
43
+
44
+ def name_for_explicit_dependency_source
45
+ 'Partfile'
46
+ end
47
+
48
+ def name_for_locking_dependency_source
49
+ 'Partfile.lock'
50
+ end
51
+
52
+ def dependencies_for(dependency)
53
+ dependency.dependencies
54
+ end
55
+
56
+ def sort_dependencies(dependencies, activated, conflicts)
57
+ dependencies.sort_by do |d|
58
+ [
59
+ activated.vertex_named(d.name).payload ? 0 : 1,
60
+ dependency_pre_release?(d) ? 0 : 1,
61
+ conflicts[d.name] ? 0 : 1,
62
+ activated.vertex_named(d.name).payload ? 0 : search_for(d).count,
63
+ ]
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def dependency_pre_release?(dependency)
70
+ dependency.requirement_list.requirements.any? do |r|
71
+ VersionKit::Version.new(r.reference_version).pre_release?
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,22 @@
1
+ module Richcss
2
+ class TestSpecification
3
+ attr_accessor :name, :version, :dependencies
4
+ def initialize(hash)
5
+ self.name = hash['name']
6
+ self.version = VersionKit::Version.new(hash['version'])
7
+ self.dependencies = hash['dependencies'].map do |(name, requirement)|
8
+ VersionKit::Dependency.new(name, requirement.split(',').map(&:chomp))
9
+ end
10
+ end
11
+
12
+ def ==(other)
13
+ name == other.name &&
14
+ version == other.version &&
15
+ dependencies == other.dependencies
16
+ end
17
+
18
+ def to_s
19
+ "#{name} (#{version})"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,34 @@
1
+ require 'molinillo'
2
+
3
+ module Richcss
4
+ class RichUI
5
+ include Molinillo::UI
6
+ # Conveys debug information to the user.
7
+ #
8
+ # @param [Integer] depth the current depth of the resolution process.
9
+ # @return [void]
10
+ def debug(depth = 0)
11
+ if debug?
12
+ debug_info = yield
13
+ debug_info = debug_info.inspect unless debug_info.is_a?(String)
14
+ STDERR.puts debug_info.split("\n").map {|s| " " * depth + s }
15
+ end
16
+ end
17
+
18
+ def debug?
19
+ ENV["DEBUG_RESOLVER"] || ENV["DEBUG_RESOLVER_TREE"]
20
+ end
21
+
22
+ def before_resolution
23
+ Bundler.ui.info "Resolving dependencies...", false
24
+ end
25
+
26
+ def after_resolution
27
+ Bundler.ui.info ""
28
+ end
29
+
30
+ def indicate_progress
31
+ Bundler.ui.info ".", false
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,3 @@
1
+ module Richcss
2
+ VERSION = "0.1.0"
3
+ end
data/lib/richcss.rb ADDED
@@ -0,0 +1,15 @@
1
+ require 'richcss/version'
2
+
3
+ module Richcss
4
+ autoload :Generators, 'richcss/generators'
5
+ autoload :Part, 'richcss/part'
6
+ autoload :Manager, 'richcss/manager'
7
+ autoload :Resolver, 'richcss/resolver'
8
+ autoload :RichSpecificationProvider, 'richcss/richcss_specification_provider'
9
+ autoload :RichUI, 'richcss/richcss_ui'
10
+ autoload :TestSpecification, 'richcss/richcss_test_specification'
11
+
12
+ class << self
13
+ # TODO
14
+ end
15
+ end
data/richcss.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'richcss/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "richcss"
8
+ spec.version = Richcss::VERSION
9
+ spec.authors = ["Nicholas Lo, Gabriel Cheng, Bill Xu, Jonathan Lai, David Zhu"]
10
+ spec.email = ["richcssa4@gmail.com"]
11
+
12
+ spec.summary = %q{This is a command line package manager for the RichCSS framework}
13
+ spec.homepage = "https://github.com/fdp-A4/richcss-cli"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = "richcss"
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.10"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "pry"
25
+
26
+ spec.add_dependency "thor"
27
+ spec.add_dependency "molinillo"
28
+ spec.add_dependency "rest-client"
29
+ spec.add_dependency "zipruby"
30
+ spec.add_dependency "email_validator"
31
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: richcss
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicholas Lo, Gabriel Cheng, Bill Xu, Jonathan Lai, David Zhu
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-03-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: molinillo
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rest-client
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: zipruby
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: email_validator
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description:
140
+ email:
141
+ - richcssa4@gmail.com
142
+ executables:
143
+ - richcss
144
+ extensions: []
145
+ extra_rdoc_files: []
146
+ files:
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - Gemfile
150
+ - LICENSE.txt
151
+ - README.md
152
+ - Rakefile
153
+ - bin/console
154
+ - bin/richcss
155
+ - bin/setup
156
+ - exe/richcss
157
+ - lib/richcss.rb
158
+ - lib/richcss/cli.rb
159
+ - lib/richcss/generator/routes.scss
160
+ - lib/richcss/generators.rb
161
+ - lib/richcss/manager.rb
162
+ - lib/richcss/part.rb
163
+ - lib/richcss/resolver.rb
164
+ - lib/richcss/richcss_specification_provider.rb
165
+ - lib/richcss/richcss_test_specification.rb
166
+ - lib/richcss/richcss_ui.rb
167
+ - lib/richcss/version.rb
168
+ - richcss.gemspec
169
+ homepage: https://github.com/fdp-A4/richcss-cli
170
+ licenses:
171
+ - MIT
172
+ metadata: {}
173
+ post_install_message:
174
+ rdoc_options: []
175
+ require_paths:
176
+ - lib
177
+ required_ruby_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ required_rubygems_version: !ruby/object:Gem::Requirement
183
+ requirements:
184
+ - - ">="
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ requirements: []
188
+ rubyforge_project:
189
+ rubygems_version: 2.2.2
190
+ signing_key:
191
+ specification_version: 4
192
+ summary: This is a command line package manager for the RichCSS framework
193
+ test_files: []