arli 0.3.2 → 0.5.1

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
  SHA1:
3
- metadata.gz: 445a4cbb2237add42b7a6dac5d41ef30cb7ffc6c
4
- data.tar.gz: 79d3becd74cabb839d0f2dfa699c1bfcfccf417e
3
+ metadata.gz: 233ae21fdec4ad9e4f6fd73c632dc632d626a5df
4
+ data.tar.gz: 4db04f61697a98c6288a81d5179bfc62fccf79ee
5
5
  SHA512:
6
- metadata.gz: 16ebcf812896a46d11cd336ab05dda084e655f549fa0468fd367226f8dd0ae012f8b91651139e5a11906f894c183cb94a91c1731eec4790f0a362575399bc3ab
7
- data.tar.gz: 21952cf71941c8b994b5b59aff00a305ab51f7abb0c98464112502e3e891c241be31518bfacb1d85bb77ad0d20c714541fd50a0a9ca77c060812f754b52b194d
6
+ metadata.gz: ca67abe8ac90302ffdf49aedfc0c3a33f999f5bc28721aa027e7f9ad104a29cbadff9bcc4ace2fed7bbb2fccf0fc6aada19f38f4096f597599c4188ed8eaf950
7
+ data.tar.gz: 1635be7126e6515ad602c68388d0e660b2536a12a5d197621c057fcec48f0641a477224cbd87072ea673c9b51c2692a9b9153e2dec1fbc6465c02816dfbb7c66
data/.gitignore CHANGED
@@ -14,3 +14,4 @@
14
14
  **/.DS_Store
15
15
  .ruby-version
16
16
  .rspec_status
17
+ !/lib/arli/commands/install.rb
@@ -1,5 +1,18 @@
1
+ env:
2
+ global:
3
+ - CC_TEST_REPORTER_ID=f8f229bdf1f374a3a9227d3bef6f57b78f88c73a2d4705c9de5852bb484eaaef
1
4
  sudo: false
2
5
  language: ruby
6
+ cache: bundler
3
7
  rvm:
4
8
  - 2.4.1
9
+ - 2.3.5
5
10
  before_install: gem install bundler -v 1.15.4
11
+ before_script:
12
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
13
+ - chmod +x ./cc-test-reporter
14
+ - ./cc-test-reporter before-build
15
+ script:
16
+ - bundle exec rspec
17
+ after_script:
18
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
data/README.md CHANGED
@@ -1,23 +1,29 @@
1
+ [![Gem Version](https://badge.fury.io/rb/arli.svg)](https://badge.fury.io/rb/arli)
1
2
  [![Build Status](https://travis-ci.org/kigster/arli.svg?branch=master)](https://travis-ci.org/kigster/arli)
3
+ [![Maintainability](https://api.codeclimate.com/v1/badges/0812671b4bec27ba89b9/maintainability)](https://codeclimate.com/github/kigster/arli/maintainability)
4
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/0812671b4bec27ba89b9/test_coverage)](https://codeclimate.com/github/kigster/arli/test_coverage)
2
5
 
3
6
  # Arli
4
7
 
5
- Arli is a simple and easy to use installer of dependencies that can be
6
- declared in a YAML file of the following format:
8
+ Arli is a simple and easy to use Arduino Dependency Manager, that uses a
9
+ a YAML formatted file declaring dependencies, as follows:
7
10
 
8
11
  ```yaml
12
+ # vi:syntax=yaml
9
13
  version: 1.0.0
10
14
  dependencies:
11
15
  - name: ESP8266WiFi
12
16
  version: '1.0'
13
17
  url: https://github.com/esp8266/Arduino
14
- subfolder: libraries/ESP8266WiFi
15
- - name: NTPClient
16
- version: '3.1.0'
18
+ - name: Time
19
+ - name: "Adafruit GFX Library"
17
20
  - name: SimpleTimer
18
- urL: https://github.com/jfturcot/SimpleTimer
21
+ url: https://github.com/jfturcot/SimpleTimer
19
22
  ```
20
23
 
24
+ The libraries may be specified with a name and url only, OR they can be specified by name (and optionally version) — as long as this is one of the standard libraries documented in the [Arduino official library database](http://downloads.arduino.cc/libraries/library_index.json.gz) JSON file.
25
+
26
+
21
27
  Basically a simple pairing of a library/project name
22
28
  (which also happens to be the local directory it's cloned into)
23
29
  and a remote URL.
@@ -31,11 +37,9 @@ API was loosely inspired by Bundler.
31
37
  Install the gem globally like this:
32
38
 
33
39
  ```bash
34
- # if using rbenv, or rvm
40
+ # if using rbenv, or rvm; otherwise you may need to prefix
41
+ # with 'sudo'
35
42
  $ gem install arli
36
-
37
- # OR, if your Ruby is a system ruby installed in eg. /usr/local,
38
- $ sudo gem install arli
39
43
  ```
40
44
 
41
45
  ## Usage
@@ -43,14 +47,18 @@ $ sudo gem install arli
43
47
  Run `arli --help` for more information:
44
48
 
45
49
  ```bash
50
+
46
51
  Usage:
47
- arli [options] [ command [options] ]
52
+ arli [options] [ command [options] ]
48
53
 
49
- -h, --help prints this help
54
+ -D, --debug Print debugging info.
55
+ -t, --trace Print exception stack traces.
56
+ -v, --verbose Print more information.
57
+ -V, --version Print current version and exit
58
+ -h, --help prints this help
50
59
 
51
60
  Available Commands:
52
- install : installs libraries defined in ArliFile.yml
53
- update : updates libraries defined in the ArliFile.yml
61
+ install : installs libraries defined in Arlifile
54
62
  search : Flexible Search of the Arduino Library Database
55
63
 
56
64
  See arli <command> --help for more information on a specific command.
@@ -66,41 +74,30 @@ target library already exists.
66
74
 
67
75
  ```bash
68
76
  Description:
69
- installs libraries defined in ArliFile.yml
77
+ installs libraries defined in Arlifile
70
78
 
71
79
  Usage:
72
80
  arli install [options]
73
81
 
74
82
  Command Options
75
- -l, --lib-home HOME Local folder where libraries are installed
76
- Default: ~/Documents/Arduino/Libraries
77
-
78
- -a, --arli-file FILE ArliFile.yml is the file listing the dependencies
79
- Default filename is ArliFile.yml
80
-
81
- -e, --abort-on-exiting Abort if a library folder already exists
82
- instead of updating it.
83
- -h, --help prints this help
84
- ```
83
+ -l, --libs PATH Local folder where libraries are installed
84
+ Defaults to ~/Dropbox/Workspace/oss/arduino/libraries
85
85
 
86
- #### Update Command
86
+ -p, --arli-path PATH Folder where Arlifile is located,
87
+ Defaults to the current directory.
87
88
 
88
- To upate previously checked out libraries, use the `update` command:
89
+ -e, --if-exists ACTION If a library folder already exists, by default
90
+ it will be overwritten or updated if possible.
91
+ Alternatively you can either abort or backup
89
92
 
90
- ```bash
91
- Description:
92
- updates libraries defined in the JSON file
93
-
94
- Usage:
95
- arli update [options]
96
-
97
- Command Options
98
- -l, --lib-home HOME Local folder where libraries are installed
99
- Default: ~/Documents/Arduino/Libraries
100
- -j, --json FILE JSON file with dependencies (defaults to arli.json)
93
+ -D, --debug Print debugging info.
94
+ -t, --trace Print exception stack traces.
95
+ -v, --verbose Print more information.
96
+ -V, --version Print current version and exit
101
97
  -h, --help prints this help
102
98
  ```
103
99
 
100
+
104
101
  #### Search Command
105
102
 
106
103
  To search Arduino library database, you can use the search command:
@@ -110,17 +107,22 @@ Description:
110
107
  Flexible Search of the Arduino Library Database
111
108
 
112
109
  Usage:
113
- arli search [options]
110
+ arli search <query> [options]
114
111
 
115
112
  Command Options
116
- -s, --search TERMS ruby-style hash arguments to search for
117
- eg: -s "name: 'AudioZero', version: /^1.0/"
118
- -d, --database SOURCE a JSON file name, or a URL that contains the index
119
- By default, the Arduino-maintained list is searched
120
- -m, --max LIMIT if provided, limits the result set to this number
121
- Default value is 100
113
+ -d FILE/URL, a JSON file name, or a URL that contains the index
114
+ --database Defaults to the Arduino-maintained list
115
+ -m, --max NUMBER if provided, limits the result set to this number
116
+ Defaults to 100
117
+ -D, --debug Print debugging info.
118
+ -t, --trace Print exception stack traces.
119
+ -v, --verbose Print more information.
120
+ -V, --version Print current version and exit
122
121
  -h, --help prints this help
123
- ```
122
+
123
+ Example:
124
+ arli search 'name: /AudioZero/, version: "1.0.1"'
125
+ I```
124
126
 
125
127
  ## Development
126
128
 
@@ -28,12 +28,13 @@ Gem::Specification.new do |spec|
28
28
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
29
29
  spec.require_paths = ['lib']
30
30
 
31
- spec.add_dependency 'arduino-library'
31
+ spec.add_dependency 'arduino-library', '~> 0.4.1'
32
32
  spec.add_dependency 'colored2'
33
33
  spec.add_dependency 'hashie'
34
34
  spec.add_dependency 'dry-types'
35
35
  spec.add_dependency 'dry-struct'
36
36
  spec.add_dependency 'awesome_print'
37
+ spec.add_dependency 'archive-zip'
37
38
 
38
39
 
39
40
  spec.add_development_dependency 'simplecov'
data/exe/arli CHANGED
@@ -6,4 +6,3 @@ Arli::CLI.new.tap do |cli|
6
6
  cli.parse
7
7
  end
8
8
 
9
-
@@ -1,41 +1,42 @@
1
- require 'arli/version'
2
- require 'arli/arli_file'
3
- require 'arli/configuration'
4
- require 'arli/cli'
1
+ require 'forwardable'
5
2
  require 'logger'
3
+ require 'arduino/library'
6
4
 
7
- module Arli
8
- LIBRARY_INDEX_JSON_GZ = 'http://downloads.arduino.cc/libraries/library_index.json.gz'.freeze
5
+ require 'arli/version'
6
+ require 'arli/errors'
7
+ require 'arli/logger'
8
+ require 'arli/config'
9
9
 
10
- DEFAULT_ARLI_FILE_ENV = 'ARDUINO_ARLI_LIBRARY_FILE'.freeze
11
- DEFAULT_ARLI_FILE = ENV[DEFAULT_ARLI_FILE_ENV] || ArliFile::DEFAULT_FILE_NAME
10
+ module Arli
12
11
 
13
- DEBUG = ENV['DEBUG'] ? true : false
12
+ class << self
13
+ attr_accessor :config
14
+ end
14
15
 
15
- @logger = Logger.new(STDOUT)
16
- @logger.level = Logger::INFO
16
+ self.config = ::Arli::Config
17
17
 
18
18
  class << self
19
- attr_accessor :logger
20
- attr_writer :configuration
19
+ extend Forwardable
20
+ def_delegators :@config, *::Arli::Config::PARAMS
21
21
 
22
- %i(debug info error warn fatal).each do |level|
23
- define_method level do |*args|
24
- self.logger.send(level, *args) if self.logger
25
- end
22
+ def configure(&_block)
23
+ yield(self.config)
26
24
  end
27
- end
28
-
29
- def self.configuration
30
- @configuration ||= Configuration.new
31
- end
32
25
 
33
- def self.reset
34
- @configuration = Configuration.new
26
+ def debug?
27
+ self.debug
28
+ end
35
29
  end
30
+ end
36
31
 
37
- def self.configure
38
- yield(configuration)
39
- end
32
+ Arli.configure do |config|
33
+ config.library_path = ::Arduino::Library::DefaultDatabase.library_path
34
+ config.library_index_path = ::Arduino::Library::DefaultDatabase.library_index_path
35
+ config.library_index_url = ::Arduino::Library::DefaultDatabase.library_index_url
36
+ config.logger = ::Logger.new(STDOUT, level: :info)
37
+ config.debug = ENV['ARLI_DEBUG'] || false
40
38
  end
41
39
 
40
+ require 'arli/arli_file'
41
+ require 'arli/installer'
42
+ require 'arli/cli'
@@ -1,24 +1,67 @@
1
1
  require 'arli'
2
- require 'arduino/library'
3
2
  require 'yaml'
3
+ require 'forwardable'
4
+ require 'arduino/library'
4
5
 
5
6
  module Arli
6
7
  class ArliFile
7
8
  require 'arduino/library/include'
8
9
 
10
+ include Enumerable
11
+
9
12
  extend Forwardable
10
13
  def_delegators :@dependencies, *(Array.new.methods - Object.methods)
11
14
 
12
- DEFAULT_FILE_NAME = 'ArliFile.yml'.freeze
15
+ attr_accessor :dependencies, :file_hash, :file, :lib_path, :resolved
13
16
 
14
- attr_accessor :dependencies, :arli_hash, :file
17
+ def initialize(lib_path: Arli.library_path,
18
+ arlifile_path: nil)
19
+
20
+ self.lib_path = lib_path
21
+ self.file = arlifile_path ? "#{arlifile_path}/#{Arli::Config::DEFAULT_FILENAME}" :
22
+ Arli::Config::DEFAULT_FILENAME
23
+ raise(Arli::Errors::ArliFileNotFound, 'Arlifile could not be found') unless file || !File.exist?(file)
24
+ self.dependencies = []
25
+
26
+ parse!
27
+ end
15
28
 
16
- def initialize(file = DEFAULT_FILE_NAME)
17
- self.file = file
18
- self.arli_hash = ::YAML.load(File.read(file))
19
- self.dependencies = arli_hash['dependencies'].map do |lib_hash|
20
- library_from(lib_hash)
29
+
30
+ def libraries
31
+ self.dependencies
32
+ end
33
+
34
+ def within_lib_path
35
+ FileUtils.mkpath(lib_path) unless Dir.exist?(lib_path)
36
+ Dir.chdir(lib_path) do
37
+ yield if block_given?
21
38
  end
22
39
  end
40
+
41
+ def each_dependency(&_block)
42
+ within_lib_path do
43
+ dependencies.each do |dependency|
44
+ yield(dependency)
45
+ end
46
+ end
47
+ end
48
+
49
+ def error(*args)
50
+ STDERR.puts *args.join("\n")
51
+ end
52
+
53
+ def info(*args)
54
+ STDOUT.puts *args.join("\n") if Arli.debug?
55
+ end
56
+
57
+ private
58
+
59
+ def parse!
60
+ self.file_hash = ::YAML.load(::File.read(self.file))
61
+ self.dependencies = file_hash['dependencies'].map do |lib|
62
+ ::Arduino::Library::Model.from_hash(lib)
63
+ end
64
+ end
65
+
23
66
  end
24
67
  end
@@ -4,19 +4,16 @@ require 'hashie/extensions/symbolize_keys'
4
4
  require 'colored2'
5
5
  require 'arli'
6
6
  require 'arli/parser'
7
- require 'arli/commands/update'
8
7
  require 'arli/commands/install'
9
8
  require 'arli/commands/search'
10
9
 
11
10
  module Arli
12
11
  class CLI
13
- class InvalidCommandError < ArgumentError;
14
- end
15
12
 
16
- COMMAND = 'arli'
13
+ COMMAND = 'arli'.freeze
17
14
  PARSER = ::Arli::CLI::Parser
18
15
 
19
- attr_accessor :argv, :command, :parser
16
+ attr_accessor :argv, :parser, :command_name, :command
20
17
  attr_accessor :options
21
18
 
22
19
  def initialize(argv = ARGV.dup)
@@ -41,53 +38,95 @@ module Arli
41
38
 
42
39
  self.options = Hashie::Extensions::SymbolizeKeys.symbolize_keys!(options.to_h)
43
40
 
44
- run_command! unless options[:help]
41
+ unless options[:help]
42
+ self.command = create_command if command_name
43
+ execute
44
+ end
45
45
 
46
- rescue InvalidCommandError => e
47
- output e.message
48
- end
46
+ rescue OptionParser::InvalidOption => e
47
+ report_exception(e, 'Command line usage error!')
49
48
 
50
- def self.output(*args)
51
- puts args.join("\n") unless args.empty?
52
- end
49
+ rescue Arli::Errors::InvalidCommandError
50
+ report_exception(e, 'This command does not exist')
53
51
 
54
- def output(*args)
55
- self.class.output(*args)
52
+ rescue Exception => e
53
+ report_exception(e)
54
+ raise e if options[:trace]
56
55
  end
57
56
 
58
57
  private
59
58
 
60
- def run_command!
61
- if command
62
- command_class = ::Arli::Commands.const_get(command.to_s.capitalize)
63
-
64
- options[:arli_file] ||= ::Arli::DEFAULT_ARLI_FILE
65
- options[:lib_home] ||= ::Arduino::Library::DEFAULT_ARDUINO_LIBRARY_PATH
59
+ def report_exception(e, header = nil)
60
+ error header.bold.yellow if header
61
+ printf ' ☠ '
62
+ error e.message if e && e.respond_to?(:message)
63
+ end
66
64
 
67
- output "run_command #{command.to_s.bold.green}, options: #{options.inspect.bold.blue}" if Arli::DEBUG
68
- @command_instance = command_class.new(options)
69
- @command_instance.header.run
65
+ def execute
66
+ if command
67
+ header
68
+ command.run
69
+ else
70
+ gp = self.class.global
71
+ gp.parse!(%w(--help))
72
+ gp.print
73
+ nil
70
74
  end
71
75
  rescue NameError => e
72
- output e.inspect
76
+ error e.inspect
77
+ error e.backtrace.join("\n") if options[:trace]
78
+ end
79
+
80
+ def create_command
81
+ command_class = ::Arli::Commands.const_get(command_name.to_s.capitalize)
82
+
83
+ options[:lib_home] ||= ::Arli.config.library_path
84
+ options[:argv] = argv
85
+
86
+ info "created command #{command_name.to_s.green},\noptions: #{options.inspect.blue}" if Arli.debug?
87
+
88
+ command_class.new(options)
89
+ end
90
+
91
+ def header
92
+ out = ''
93
+ out << "Arli (#{::Arli::VERSION.yellow})"
94
+ out << " running #{command.name.to_s.blue}" if command
95
+ out << "\n"
96
+ out << "Library Folder: #{options[:lib_home].gsub(/#{ENV['HOME']}/, '~').green}\n" if options[:lib_home]
97
+ out << '——————————————————————————————————————————————————————————'
98
+ info out
99
+ end
100
+
101
+ def info(*args)
102
+ self.class.output(*args)
103
+ end
104
+
105
+ def error(*args)
106
+ self.class.output(*(args.compact.map { |a| a.to_s.red }))
73
107
  end
74
108
 
75
109
  def parse_command_options!
76
- self.class.parser_for(command)
110
+ self.class.parser_for(command_name)
77
111
  end
78
112
 
79
113
  def command_detected?
80
- self.command = argv.shift if argv.first && argv.first !~ /^-.*$/
81
- if self.command
82
- self.command = command.to_sym
83
- unless self.class.commands.key?(command)
84
- raise InvalidCommandError, "Error: #{command ? command.to_s.bold.red : 'nil'} is not a valid arli command!"
114
+ self.command_name = argv.shift if argv.first && argv.first !~ /^-.*$/
115
+ if self.command_name
116
+ self.command_name = command_name.to_sym
117
+ unless self.class.commands.key?(command_name)
118
+ raise Arli::Errors::InvalidCommandError, "Error: #{command_name ? command_name.to_s.red : 'nil'} is not a valid arli command_name!"
85
119
  end
86
120
  end
87
- self.command
121
+ self.command_name
88
122
  end
89
123
 
90
124
  class << self
125
+
126
+ def output(*args)
127
+ puts args.join("\n") unless args.empty?
128
+ end
129
+
91
130
  def global
92
131
  @global ||= PARSER.new do |parser|
93
132
  parser.banner = usage_line
@@ -101,63 +140,43 @@ module Arli
101
140
  end
102
141
 
103
142
  def global_usage(command)
104
- "Usage:\n ".bold + COMMAND.bold.blue +
105
- ' [options] '.yellow + '[' + (command || 'command').green +
106
- ' [options]'.yellow + ']' + "\n"
143
+ "Usage:\n " + COMMAND.blue +
144
+ ' [options] '.yellow + '[ ' + (command || 'command').green +
145
+ ' [options] '.yellow + ' ]' + "\n"
107
146
  end
108
147
 
109
148
  def command_usage(command)
110
- "Usage:\n ".bold + COMMAND.bold.blue + ' ' +
111
- command.bold.green +
149
+ "Usage:\n " + COMMAND.blue + ' ' +
150
+ command.green +
112
151
  ' [options]'.yellow + "\n\n" +
113
- 'Command Options'.bold
152
+ 'Command Options'
114
153
  end
115
154
 
116
155
  def commands
117
156
  @commands ||= {
118
157
  install: {
119
- description: 'installs libraries defined in ArliFile.yml',
120
- parser: -> (command) {
158
+ description: 'installs libraries defined in Arlifile',
159
+ parser: -> (command_name) {
121
160
  PARSER.new do |parser|
122
161
  parser.banner = usage_line 'install'
123
162
  parser.option_lib_home
124
163
  parser.option_dependency_file
125
164
  parser.option_abort_if_exists
126
- parser.option_help(command: command)
127
- end
128
- } },
129
-
130
- update: {
131
- description: 'updates libraries defined in the ArliFile.yml',
132
- parser: -> (command) {
133
- PARSER.new do |parser|
134
- parser.banner = usage_line 'update'
135
- parser.option_lib_home
136
- parser.option_dependency_file
137
- parser.option_help(command: command)
165
+ parser.option_help(command_name: command_name)
138
166
  end
139
167
  } },
140
168
 
141
169
  search: {
142
170
  description: 'Flexible Search of the Arduino Library Database',
143
- parser: -> (command) {
171
+ example: 'arli search '.green + %Q['name: /AudioZero/, version: "1.0.1"'].green,
172
+ parser: -> (command_name) {
144
173
  PARSER.new do |parser|
145
- parser.banner = usage_line 'search'
174
+ parser.banner = usage_line 'search ' + '<query>'.magenta
146
175
  parser.option_search
147
- parser.option_help(command: command)
176
+ parser.option_help(command_name: command_name)
148
177
  end
149
- } }
150
-
151
- # library: {
152
- # description: 'Install, update, or remove a single library',
153
- # parser: -> (command) {
154
- # PARSER.new do |parser|
155
- # parser.banner = usage_line 'library'
156
- # parser.option_lib_home
157
- # parser.option_library
158
- # parser.option_help(command: command)
159
- # end
160
- # } }
178
+ }
179
+ }
161
180
  }
162
181
  end
163
182
 
@@ -166,7 +185,8 @@ module Arli
166
185
  cmd_hash = commands[cmd]
167
186
  commands[cmd][:parser][cmd_hash]
168
187
  else
169
- raise(InvalidCommandError, "'#{cmd}' is not a valid command.\nSupported commands are:\n\t#{commands.keys.join("\n\t")}")
188
+ raise(Arli::Errors::InvalidCommandError,
189
+ "'#{cmd}' is not a valid command_name.\nSupported commands are:\n\t#{commands.keys.join("\n\t")}")
170
190
  end
171
191
  end
172
192
  end